"used as non-type template parameter" 是否使函数模板隐式实例化?
Does "used as non-type template parameter" make a function template implicitly instantiated?
我想编写一个 class 模板 M
接受不完整类型 C
作为模板参数。
但我也希望 C
在最终定义时具有一些特征。
这个码有保证吗
- 编译如果定义(FLAG),
- 如果 !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)
A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule (6.2), the program is ill-formed, no diagnostic required.
首先,请注意,主要模板是 paa0ssed 参数,是标准语言的专业化。根据我的经验,C++ 程序员使用它的方式与标准不同。
其次,check<Test>
在你的程序中有两个实例化点;曾经在
M<Test> m;
并在翻译单元末尾出现一次。
M<Test> m
处check<Test>
的含义与翻译单元末尾check<Test>
的含义不同。在一个地方,Test
是不完整的,在另一个地方是完整的。 check<Test>
的正文肯定有不同的含义。
所以你的程序格式错误,不需要诊断。在您的情况下,格式错误的程序恰好可以执行您想要的操作,但它可以(在标准下)编译成任何东西,或者无法编译。
我怀疑这条规则背后的原因是让编译器可以自由地立即实例化 check
或将其推迟到以后实例化。您不能依赖它实际执行 check
.
主体实例化的两个点中的哪一个
我想编写一个 class 模板 M
接受不完整类型 C
作为模板参数。
但我也希望 C
在最终定义时具有一些特征。
这个码有保证吗
- 编译如果定义(FLAG),
- 如果 !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)
A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule (6.2), the program is ill-formed, no diagnostic required.
首先,请注意,主要模板是 paa0ssed 参数,是标准语言的专业化。根据我的经验,C++ 程序员使用它的方式与标准不同。
其次,check<Test>
在你的程序中有两个实例化点;曾经在
M<Test> m;
并在翻译单元末尾出现一次。
M<Test> m
处check<Test>
的含义与翻译单元末尾check<Test>
的含义不同。在一个地方,Test
是不完整的,在另一个地方是完整的。 check<Test>
的正文肯定有不同的含义。
所以你的程序格式错误,不需要诊断。在您的情况下,格式错误的程序恰好可以执行您想要的操作,但它可以(在标准下)编译成任何东西,或者无法编译。
我怀疑这条规则背后的原因是让编译器可以自由地立即实例化 check
或将其推迟到以后实例化。您不能依赖它实际执行 check
.