以下是无效的代码:
struct foo {
struct bar;
bar x; // error: field x has incomplete type
struct bar{ int value{42}; };
};
int main() { return foo{}.x.value; }
这很清楚,因为foo::bar
在foo::x
定义的位置被认为是不完整的。
但是,似乎有一个“替代方法”使相同的类定义有效:
template <typename = void>
struct foo_impl {
struct bar;
bar x; // no problems here
struct bar{ int value{42}; };
};
using foo = foo_impl<>;
int main() { return foo{}.x.value; }
这适用于所有主要编译器。我对此有三个问题:
template
)被认为无效?如果编译器可以找出第二个选项,那么我看不出为什么它不能找出第一个选项的原因。如果我为以下内容添加明确的专业化void
:
template <typename = void>
struct foo_impl {};
template<>
struct foo_impl<void> {
struct bar;
bar x; // error: field has incomplete type
struct bar{ int value{42}; };
};
using foo = foo_impl<>;
int main() { return foo{}.x.value; }
它再次无法编译。
真正的答案可能是\\(())_ /,但由于模板具有魔力,目前可能尚可,但在其他一些核心问题解决方案之前,它可能显然不可行。
首先,主要的问题当然是[class.mem] / 14:
非静态数据成员不应具有不完整的类型。
这就是为什么您的非模板示例格式错误的原因。但是,根据[temp.point] / 4:
对于类模板专业化,类成员模板专业化或对类模板的类成员的专业化,如果该专业化是隐式实例化的,因为该专业化是从另一个模板专业化内部引用的,则如果引用该专业化的上下文取决于在模板参数上,并且如果未在封闭模板的实例化之前实例化专业化,则实例化点紧接在封闭模板的实例化点之前。否则,此类专门化的实例化点紧接在引用该专门化的名称空间范围声明或定义之前。
这表明该foo_impl<void>::bar
对象在之前 实例化foo_impl<void>
,因此在bar
实例化类型的非静态数据成员时就完成了该操作。所以也许没关系。
但是,核心语言问题1626和2335处理的关于完整性和模板的问题不完全相同,但仍然非常相似,并且都指向希望使模板用例与非模板用例更加一致。
从整体上看,这意味着什么?我不确定。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句