当不需要检查缩小时,是否需要实例化函数定义?

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

考虑以下程序:

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>()} ) );

根据我的理解,最后一行是一个错误,因为对 f<double>() 的调用是在大括号初始值设定项中,即使 f<T> returns 和 int,需要返回 int 的值来决定是否可以将其缩小为 g 所期望的 char。这需要用 double 实例化 f 的定义,这会导致错误。 gcc 和 clang 都拒绝此代码。


但是,如果 g 的定义更改为接受 int 参数:

constexpr void g(int);

那么好像不需要实例化f的定义,因为缩小转换必须成功。事实上,gcc 接受这个,但 clang 仍然用 double 实例化 f 并拒绝 code。此外,如果仅声明 f 而未定义,则 clang 接受代码,这意味着不需要定义,也不应实例化。

我的推理是否正确,这是一个 clang 错误,还是需要实例化,这实际上是一个 gcc 错误?

这是CWG #1581 I think, resolved by P0859

temp.inst/5 说:

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.

存在是否影响程序的语义?

temp.inst/8 说:

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.

是否需要通过表达式进行常量求值?

expr.const/15.6-7 说:

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.

它是由一个可能被评估为常量的表达式命名的吗?

expr.const/15.1-15.5 说:

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.

它是 braced-init-list 的直接子表达式。