In C++11 I am using a constexpr function as a default value for a template parameter - it looks like this:
template <int value>
struct bar
{
static constexpr int get()
{
return value;
}
};
template <typename A, int value = A::get()>
struct foo
{
};
int main()
{
typedef foo<bar<0>> type;
return 0;
}
G++ 4.5 and 4.7 compiles this, but Clang++ 3.1 does not. The error message from clang is:
clang_test.cpp:10:35: error: non-type template argument is not a constant expression
template <typename A, int value = A::get()>
^~~~~~~~
clang_test.cpp:17:19: note: while checking a default template argument used here
typedef foo<bar<3>> type;
~~~~~~~~~^~
clang_test.cpp:10:35: note: undefined function 'get' cannot be used in a constant expression
template <typename A, int value = A::get()>
^
clang_test.cpp:4:23: note: declared here
static constexpr int get()
^
1 error generated.
Which one is correct?
A call to a constexpr function produces the same result as a call to an equivalent non- constexpr function , except that a call to a constexpr function can appear in a constant expression. The main function cannot be declared with the constexpr specifier.
The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const , it can be applied to variables: A compiler error is raised when any code attempts to modify the value. Unlike const , constexpr can also be applied to functions and class constructors.
A constexpr function is a function that can be invoked within a constant expression. A constexpr function must satisfy the following conditions: It is not virtual. Its return type is a literal type.
The easiest way to check whether a function (e.g., foo ) is constexpr is to assign its return value to a constexpr as below: constexpr auto i = foo(); if the returned value is not constexpr compilation will fail.
Richard Smith (zygoloid) at the LLVM IRC channel had a short talk with me about this issue which is your answer
<litb> hello folks
<litb> zygoloid, what should happen in this case?
<litb> http://stackoverflow.com/questions/10721130/calling-constexpr-in-default-template-argument
<litb> it seems to be clang's behavior is surprising
<litb> zygoloid, i cannot apply the "point of instantiation" rule to constexpr
function templates. if i call such a function template, the called definition's
POI often is *after* the specialization reference, which means at the point of
the call, the constexpr function template specialization is "undefined".
<zygoloid> it's a horrible mess. Clang does not do what the standard intends, but
as you note, the actual spec is gloriously unclear
<d0k> :(
<zygoloid> we should instantiate bar<3>::get(), because it is odr-used, but we
don't, because we incorrectly believe it's used in an unevaluated context
<zygoloid> conversely, the point of instantiation is too late :/
<zygoloid> PR11851
So it seems that sometimes, Clang instantiates called function templates or member function of class templates but their instantiation is too late for the call to see, and at other cases it doesn't even instantiate them because it thinks it will never need them (unevaluated context).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With