2

Call to the extract function below does not work for me on g++ 4.9.0 (20130421). The error I get is that s1 is not a constant expression. If i can be initialized as constexpr then j and k should too. Is that wrong?

#include <tuple>

template <unsigned N1, unsigned N2> 
constexpr bool strmatch(const char (&s1)[N1], const char (&s2)[N2], unsigned i = 0)
{
  return (s1[i]==s2[i]) ? 
            (s1[i]=='\0') ? 
               true
               : strmatch(s1, s2, i+1) 
            : false;
}

template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
  return std::get<strmatch(array, "m0")>(t1);
}

int main(void)
{
  constexpr int i = strmatch("m0", "m0");  // OK
  constexpr int j = extract(std::make_tuple(10, 20), "m0"); 
  constexpr int k = extract(std::make_tuple(10, 20), "m1");

  return 0;
}
1
  • I'm 75% sure this is a compiler bug. Function invocation substitution ought to clean up any reference binding issues. Commented May 11, 2013 at 0:15

1 Answer 1

1

Your code is ill-formed. The problem is that array is not a core constant expression, so can't be used in the template argument in the call to std::get:

template<unsigned N>
constexpr int extract(const std::tuple<int, int> & t1, const char (&array)[N]) {
  return std::get<strmatch(array, "m0")>(t1);
}

Remember that constexpr functions can be called at runtime: this code would use the value of a runtime parameter to this function (array) during translation (in the evaluation of the call to strmatch).

Sign up to request clarification or add additional context in comments.

4 Comments

That's pretty lame! I can assign the result of strmatch to a constexpr integer (i) and use it as a template argument for std::get. I should be able to do just that without having to use a named variable. Isn't that the idea behind function invocation substitution?
Function invocation substitution is just a formalism to describe how the function call is evaluated. To reiterate, your function extract<3> can be called at runtime, which would in general require template instantiation to happen at runtime if this were allowed.
Right. But as long as all the invocations (in a translation unit) of extract<N> can be evaluated at compile-time, the code should work, right?
No, the function must still work at runtime even if you never happen to call it that way. constexpr is not like template instantiation -- it does not let you generate code (which would be necessary if you could use parameters to constexpr functions in template arguments).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.