c++ - 类中不允许不完整类型,但类模板中允许使用不完整类型

标签 c++ c++11 templates language-lawyer forward-declaration

以下是无效代码:

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; }

这个 works与所有主要编译器。 我对此有三个问题:

  1. 这确实是有效的 C++ 代码,还是只是编译器的怪癖?
  2. 如果是有效代码,C++ 标准中是否有段落处理此异常?
  3. 如果是有效代码,为什么第一个版本(没有模板)被认为是无效的?如果编译器可以找出第二个选项,我看不出它无法找出第一个选项的原因。

如果我为 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; } 

再次fails to compile .

最佳答案

真正的答案可能是¯\_(ツ)_/¯,但目前可能还可以,因为模板很神奇,但在其他一些核心问题解决之前,它可能更明确地不行。

首先,主要问题当然是[class.mem]/14 :

Non-static data members shall not have incomplete types.

这就是您的非模板示例格式错误的原因。然而,根据 [temp.point]/4 :

For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template. Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.

这表明 foo_impl<void>::bar被实例化之前 foo_impl<void> ,因此它在类型为 bar 的非静态数据成员处完成。被实例化。所以也许没关系。

然而,核心语言问题 16262335处理关于完整性和模板的不完全相同但仍然非常相似的问题,并且都指向希望使模板案例与非模板案例更加一致。

从整体上看,这一切意味着什么?我不确定。

关于c++ - 类中不允许不完整类型,但类模板中允许使用不完整类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50202718/

相关文章:

c++ - 关于 C++ 中的 sleep 命令

c++ - 从 'enable_shared_from_this' 派生一个类可以提高性能吗?

c++ - 嵌套在模板类中的模板类在 MSVC++ 中给出错误

c++ - WinMain 参数

c++ - 带有自定义* .o文件的“ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000”

c++ - 指向失去值(value)的对象的 vector 的指针

c++ - 如何返回嵌套在其他包中的模板包?

c++ - 如何仅从 linux SO 库中导出某些函数?

c++ - 我是否在这个通用的 unique_ptr<>() 删除器中正确使用了指针类?

c++ - 跨命名空间覆盖运算符