【发布时间】:2018-09-06 09:39:20
【问题描述】:
标题中的问题很清楚。更具体地说,请考虑以下示例:
#include <type_traits>
template <typename T>
struct is_complete_helper {
template <typename U>
static auto test(U*) -> std::integral_constant<bool, sizeof(U) == sizeof(U)>;
static auto test(...) -> std::false_type;
using type = decltype(test((T*)0));
};
template <typename T>
struct is_complete : is_complete_helper<T>::type {};
// The above is an implementation of is_complete from https://stackoverflow.com/a/21121104/5376789
template<class T> class X;
static_assert(!is_complete<X<char>>::type{});
// X<char> should be implicitly instantiated here, an incomplete type
template<class T> class X {};
static_assert(!is_complete<X<char>>::type{}); // #1
X<char> ch; // #2
此代码compiles with GCC and Clang。
除非类模板特化已被显式实例化或显式特化,否则当在需要完全定义的对象类型的上下文中引用该类模板特化或当类类型的完整性时,将隐式实例化类模板特化影响程序的语义。
X<char> 被隐式实例化,因为static_assert(!is_complete<X<char>>::type{}) 会生成不完整的类型。
然后,在X 的定义之后,#1 表明X<char> 没有再次实例化(仍然不完整),而#2 表明X<char> 确实再次实例化了(成为一个完整的类型)。
如果一个特化已经被隐式实例化,它是否会被隐式实例化?为什么#1 和#2 有区别?
欢迎对标准进行解释。
【问题讨论】:
-
IIRC,这打破了 odr。
-
@YSC 你的意思是#1 和#2 打破了 odr 吗?但它是如此普遍,以至于一个专业化被多次引用......
-
我错了,如果涉及多个 TU,就会破坏 odr,根据 [temp.point]/8。
-
我认为该程序的 NDR 格式不正确,因为
is_complete<X<char>>::type取决于实例化点(包括 EOF 之一)。 -
@Jarod42 - EOF 仅用于函数。类只有一个 POI。
标签: c++ templates language-lawyer template-instantiation implicit-instantiation