简体   繁体   中英

Is this error message correct: non-type template argument is not a constant expression

The following program compiles with GCC 5.2, but not with clang 3.6:

constexpr bool flag();

template <bool b = flag()>
constexpr bool test() 
{ 
    return b;
}

int main() 
{
}

The error message I get with clang is:

main.cpp:3:20: error: non-type template argument is not a constant expression
template <bool b = flag()>
                   ^~~~~~
main.cpp:3:20: note: undefined function 'flag' cannot be used in a constant expression
main.cpp:1:16: note: declared here
constexpr bool flag();
               ^
main.cpp:4:16: error: no return statement in constexpr function
constexpr bool test() 
               ^

My question is: Who's right? Or, in other words: Is the program ill-formed?

I'd say that clang is right:

From the Standard:

[temp.param] 14.1 #9

9 A default template-argument is a template-argument (14.3) specified after = in a template-parameter. [...]

And [temp.arg.nontype] 14.3.2

1 A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter.

And [expr.const] 5.20

2 A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

[...]

(2.3) — an invocation of an undefined constexpr function or an undefined constexpr constructor;

Since flag() is declared but not defined, it is not a constant expression and 14.3.2 is violated.

According to ISO C++14 Standard 5.19.2:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

  • this (5.1.1), except in a constexpr function or a constexpr constructor that is being evaluated as part of e;
  • an invocation of a function other than a constexpr constructor for a literal class, a constexpr function, or an implicit invocation of a trivial destructor (12.4) [ Note: Overload resolution (13.3) is applied as usual — end note ];
  • an invocation of an undefined constexpr function or an undefined constexpr constructor;
  • (...) Blockquote

The result of any constexpr function call made prior to it definition is not a constant expression.

Finally it seems that it is GCC bug.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM