考虑一些函数模板,例如:
template <class T>
const auto& foo() { static T t; return t; }
Run Code Online (Sandbox Code Playgroud)
如果T是 ,则定义将无效void。尽管如此,我们可以单独实例化声明而不触发错误:
extern template const auto& foo<void>(); // explicit instantiation declaration
Run Code Online (Sandbox Code Playgroud)
现在让我们考虑foo被调用而不是被显式实例化的情况。显然,如果foo在评估的上下文中被调用,特化的定义将被实例化。在未评估的情况下呢?我们知道,如果在未计算的上下文中调用具有非推导返回类型的函数模板,则不会实例化特化的定义。一个明显的例子是std::declval<T>. 尚不清楚对于具有推导返回类型的函数是否可能相同。
例如,我考虑过这个:
static_assert(sizeof( (void)foo<void>(), char{} ) == 1);
Run Code Online (Sandbox Code Playgroud)
然而,即使在这种情况下,编译器肯定有足够的信息来评估sizeof表达式而不知道返回类型,编译错误仍然会发生(godbolt link)。
foo<void>在这种情况下,标准的哪些规定需要实例化的定义?foo<void>可以在不会实例化其定义的未计算表达式中调用吗?