Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
341 views
Welcome To Ask or Share your Answers For Others

1 Answer

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...