为什么我的班级不是默认可构造的?

问题描述 投票:23回答:2

我有那些课程:

#include <type_traits>

template <typename T>
class A {
public:
    static_assert(std::is_default_constructible_v<T>);

};

struct B {
   struct C {
      int i = 0;
   };

    A<C> a_m;
};

int main() {
    A<B::C> a;
}

[编译时,a_m不是默认可构造的,但a是。

C更改为:

struct C {
      int i;
   };

一切都很好。

使用Clang 9.0.0测试。

c++
2个回答
0
投票

按书:A<C>的实例化点是immediately before the definition of B,而B的实例化点紧接在此之前:

对于类模板专业化,如果专业化是隐式实例化,因为它是从另一个内部引用的模板专业化,如果专业化所来自的上下文被引用取决于模板参数,以及没有在实例化之前实例化专门化封闭模板,实例化点是立即在封闭模板的实例化点之前。否则,这种专业化的实例化点紧接在名称空间范围声明或定义之前指的是专业化。

由于std::is_default_constructible<C>在那时显然是不完整的,因此实例化C的行为是不确定的。但是,请参见std::is_default_constructible<C>


实际上:

  • NSDMI很奇怪,因为它们被延迟解析-或者按照标准的说法,它们是“完整类上下文”。
  • 因此,core issue 238原则上可以引用= 0中尚未声明的内容,因此实现在完成B之前无法真正尝试解析它。
  • 完成类需要隐式声明特殊成员函数,尤其是默认构造函数,因为B没有声明构造函数。
  • 该声明的部分(constexpr-ness,noexcept-ness)取决于NSDMI的属性。
  • 因此,如果编译器无法解析NSDMI,则它将无法完成该类。

-1
投票

C它是:

如果上述模板的实例直接或直接取决于间接地,对于不完整的类型,该实例化可以产生如果假设该类型已完成,则结果会不同,行为是不确定的。

© www.soinside.com 2019 - 2024. All rights reserved.