请考虑以下代码:
template <class T>
struct computation {
using type = /* something based on T that takes time to compile */;
};
现在考虑两个代码:
using x = computation<T>;
和:
using y = typename computation<T>::type;
我想知道该标准是否意味着:
- 选项 A)任何"合理"的编译器都会导致
x
的快速编译时间和较长的编译时间y
- 选项 B)即使只调用
computation<T>
,编译器也可以完全计算computation<T>::type
,即使对于x
,也会导致很长的编译时间
换句话说,我试图知道该标准是否指定了最有可能转化为"合理"编译器计时器的选项 A 或选项 B 的任何内容。我知道该标准没有提到编译器实现,但是例如,如果它要求::type
在被专门调用之前不必存在,那将有利于选项A。
注意:根据我的经验,我很确定g++
、clang++
、msvc
和intel
都遵循选项 A),但我不知道这是否只是纯粹的运气,因为它与标准中的某些内容有关。
我假设T
在这里是一个实际的非依赖类型,而不是另一个模板参数。
生产线
using x = computation<T>;
不会导致computation<T>
的隐式实例化。因此,编译器没有理由在这一点上尝试计算type
,特别是因为任何实例化失败都需要忽略。如果type
的计算会产生无效的类型或失败,程序可能不会编译失败。
该行
using y = computation<T>::type;
确实需要隐式实例化computation<T>
因为范围解析运算符应用于它。隐式实例化包括计算computation<T>
中的类型别名。编译器必须执行计算,因为如果计算失败或生成无效类型,则程序格式不正确,编译器需要对其进行诊断。
这实际上并不具体取决于::type
部分。即使它::type2
为另一个类型别名,类模板专用化的隐式实例化也需要计算type
。
类似地,在任何其他需要其完整的上下文中使用computation<T>
将需要隐式实例化,因此需要计算type
,例如
auto z = computation<T>{};