考虑一些功能模板,例如:
template <class T>
const auto& foo() { static T t; return t; }
如果T
是void
,则该定义将无效。尽管如此,我们仍然可以单独实例化声明而不会触发错误:extern template const auto& foo<void>(); // explicit instantiation declaration
现在让我们考虑调用foo
而不是对其进行显式实例化的情况。显然,如果曾经在评估的上下文中调用foo
,则将实例化专门化的定义。在未经评估的情况下呢?我们知道,如果在未求值的上下文中调用具有非推断返回类型的函数模板,则不会实例化专门化的定义。显而易见的示例是std::declval<T>
。尚不清楚具有推导的返回类型的函数是否可以实现相同的功能。例如,我考虑了这一点:
static_assert(sizeof( (void)foo<void>(), char{} ) == 1);
但是,即使在这种情况下,即使编译器确实具有足够的信息来评估sizeof
表达式而又不知道返回类型,仍然会发生编译错误(godbolt link)。foo<void>
的定义? foo<void>
? 最佳答案
尽管不是规范性的,但是[dcl.spec.auto]/11中的注释确实提到(对声明为返回值的占位符的函数模板使用特殊化)任何使用都会导致隐式实例化[提取,强调我的名字]:
而且,[dcl.spec.auto]/14涵盖了允许在不触发实例化的情况下进行显式实例化声明的特殊情况,同时可以说还暗示了为确定函数模板的返回类型而触发的实例化机制与“常规”实例化机制有所分离[重点我的]:
该示例的注释(非规范性的)指出,这种特殊情况触发的隐式实例化仅用于返回类型推导,而无需在其他地方放弃对显式实例化定义的需求。
鉴于以上讨论,我会说:不。即使在未经评估的表达式内进行调用也将属于(非规范性)“对...的任何使用”。
关于c++ - 如果函数模板具有推导的返回类型,是否可以在不实例化定义的情况下调用它?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64915753/