【发布时间】:2020-11-19 16:21:14
【问题描述】:
考虑一些函数模板,例如:
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>?
【问题讨论】:
-
标准的哪些规定要求在这种情况下实例化 foo
的定义? 标准仅在获取函数timsong-cpp.github.io/cppwp/n4659/temp.deduct.funcaddr#2 的地址时才要求: / -
我问a related question,类模板的非模板成员函数的特化的显式实例化声明似乎会导致相关类模板特化的实例化(根据 GCC/Clang)。推导出成员函数的返回类型可能与我的问题无关,但我主要使用它来获得 [dcl.spec.auto]/14 的支持,即显式实例化声明不应导致实例化。
-
我们知道,如果在未计算的上下文中调用具有非推导返回类型的函数模板,则特化的定义不会被实例化我认为是CWG1378.
标签: c++ templates language-lawyer