当不需要检查缩小时,是否需要实例化函数定义?
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.
是否需要通过表达式进行常量求值?
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.
它是由一个可能被评估为常量的表达式命名的吗?
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 的直接子表达式。
考虑以下程序:
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.
是否需要通过表达式进行常量求值?
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.
它是由一个可能被评估为常量的表达式命名的吗?
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 的直接子表达式。