c++ - “用作非类型模板参数”是否使函数模板隐式实例化?
问题描述
我想编写一个M
接受不完整类型C
作为模板参数的类模板。但我也希望C
在最终定义时具有一些特征。
此代码是否有保证
- 编译如果定义(标志),
- 如果 !defined(FLAG) 编译失败?
template <auto> struct Dummy {};
template <typename C>
void check()
{
static_assert(std::is_trivial_v<C>);
}
template <typename C>
struct M : Dummy<&check<C>>
{
//static_assert(std::is_trivial_v<C>);//error: incomplete type
C * p;
};
struct Test;
M<Test> m;
int main()
{
return 0;
}
#if defined(FLAG)
struct Test {};
#else
struct Test { std::string non_trivial_member; };
#endif
解决方案
实例化点 [temp.point] (17.7.4.1/8)
函数模板、成员函数模板或类模板的成员函数或静态数据成员的特化可以在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于任何此类在翻译单元内有一个实例化点的特化,翻译单元的末端也被认为是一个实例化点。类模板的特化在翻译单元内最多有一个实例化点。任何模板的特化都可能在多个翻译单元中具有实例化点。如果根据单定义规则(6.2),两个不同的实例化点赋予模板特化不同的含义,则程序是非良构的,不需要诊断。
首先,请注意主要模板被 paa0ssed 参数是标准语言的专业化。根据我的经验,C++ 程序员使用它的方式与标准不同。
其次,check<Test>
在你的程序中有两个实例化点;曾经在
M<Test> m;
一次在翻译单元的末尾。
check<Test>
at的含义与翻译单元末尾的M<Test> m
含义不同。check<Test>
一方面Test
是不完整的,另一方面是完整的。身体check<Test>
肯定有不同的含义。
所以你的程序格式不正确,不需要诊断。在您的情况下,格式错误的程序恰好可以执行您想要的操作,但它可以(根据标准)编译成任何东西,或者无法编译。
我怀疑这条规则背后的原因是让编译器可以自由地check
立即实例化或推迟到稍后实例化。你不能依赖它实际实例化的两个点中的哪一个check
。
推荐阅读
- html - 如何防止三个单独的“。” 字符从成为 HTML 中的单字符省略号?
- parsing - 将 grep 的输出解析为标记文件
- python - 无法在熊猫数据框中正确解码重音
- testing - 使内部声明对 Kotlin 中的其他模块可见
- javascript - 如何循环/显示来自 json 的所有作者
- oracle - LiquiBase 向 Oracle 插入重音字符
- reactjs - 为什么我在 react.js 中的函数在 codepen 中不起作用?
- vmware-clarity - 如何从 Clarity Datagrid 中获取过滤和排序的结果集?
- java - 时间:2019-05-10 标签:c#consumer http body而不等待流/body的结束
- c - 为什么这个模运算在我的旋转字符串函数中不正确?