Question

So I'm playing around with templates & constexpr, specifically variadic templates and I made the following functions:

template <typename T>
constexpr T get_argument(size_t index)
{
  return T();
};

template <typename T, T arg, T... args>
constexpr T get_argument(size_t index)
{
  return index ? get_argument<T,args...>(index-1) : arg;
}

The terminating function here is currently a dummy placeholder. So this function works, but returns a 0 if out of range, what I'd like it to do is crash...but it would need 2 modalities of failure. get_argument could be called at compile time, in which I'd want index being out of range to cause a compiler error. Or it could be called at runtime, in which I would like it to throw a runtime error...

I also have the option of this:

template <typename T>
constexpr T get_argument(size_t index)
{
  return false ? T() : throw std::out_of_range("Index out of argument range");
}

template <typename T, T arg, T... args>
constexpr T get_argument(size_t index)
{
  return index ?
        (count_args<T,args...>() ?
           get_argument<T,args...>(index-1) :
           throw std::out_of_range("Index out of argument range")) :
        arg;
}

But 1) I don't like the syntax (always false conditional, plus checking twice in a vague attempt to get the output to mean something), and 2) The errors is messy:

test.hpp:32:69: error: expression '<throw-expression>' is not a constant-expression
            throw std::out_of_range("Index out of argument range")) :

Anyone have a better way?

Was it helpful?

Solution

Following may help (only one check):

template <typename T, T ... Ts>
constexpr std::array<T, sizeof...(Ts)> getArray()
{
    return {{Ts...}};
}

template <typename T, T ... Ts>
constexpr T get_argument(size_t index)
{
  return index < sizeof...(Ts) ?
    const_cast<const std::array<T, sizeof...(Ts)>&&>(getArray<T, Ts...>())[index] :
    throw std::out_of_range("Index out of argument range");;
}

C++14 may help, possibility to have several statements, as:

  • local variable (which remove the need of this const_cast)
  • assert (in possible addition to throw).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top