Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a function definition required to be instantiated when there is no need to check for narrowing?

Consider the following program:

template<typename T>
constexpr int f() 
{
    T{}.i; // error if instantiated with [T = double]
    return 42;
}

constexpr void g(char);

using U = decltype( g( {f<double>()} ) );

To my understanding, the last line is an error because the call to f<double>() is within a brace initializer, and even though f<T> returns an int, the value of the returned int is needed to decide if it can be narrowed to a char as expected by g. This requires the definition of f to be instantiated with double, which causes an error. Both gcc and clang reject this code.


However, if the definition of g is changed to accept an int parameter:

constexpr void g(int);

then it seems that there is no need to instantiate the definition of f, since the narrowing conversion must succeed. Indeed, gcc accepts this, but clang still instantiates f with double and rejects the code. Additionally, if f is only declared, but not defined, clang accepts the code, which implies that the definition is not needed, and shouldn't be instantiated.

Is my reasoning correct, and this is a clang bug, or is instantiation required, and this is actually a gcc bug?

like image 733
cigien Avatar asked Aug 24 '20 02:08

cigien


1 Answers

This is CWG #1581 I think, resolved by P0859.

temp.inst/5 says:

Unless a function template specialization is a declared specialization, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.

Does the existence affect the semantics of the program?

temp.inst/8 says:

The existence of a definition of a variable or function is considered to affect the semantics of the program if the variable or function is needed for constant evaluation by an expression ([expr.const]), even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition.

Is it needed for constant evaluation by an expression?

expr.const/15.6-7 says:

A function or variable is needed for constant evaluation if it is:

  • a constexpr function that is named by an expression that is potentially constant evaluated, or
  • a variable whose name appears as a potentially constant evaluated expression that is either a constexpr variable or is of non-volatile const-qualified integral type or of reference type.

Is it named by an expression that is potentially constant evaluated?

expr.const/15.1-15.5 says:

An expression or conversion is potentially constant evaluated if it is:

  • a manifestly constant-evaluated expression,
  • a potentially-evaluated expression,
  • an immediate subexpression of a braced-init-list,
  • an expression of the form & cast-expression that occurs within a templated entity, or
  • a subexpression of one of the above that is not a subexpression of a nested unevaluated operand.

It is an immediate subexpression of a braced-init-list.

like image 82
Jeff Garrett Avatar answered Sep 22 '22 21:09

Jeff Garrett