是否可以实例化具有已删除的构造函数和析构函数的非聚合类?

时间:2018-04-11 11:06:57

标签: c++ object casting instantiation c++17

考虑以下课程:

ul.newclass {
 list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #C0C0C0;
  border-bottom: solid #008348;
}

ul.newclass li {
  float: left;
 }

ul.newclass li a {
 display: block;
 color: #000000;
 font-size: 15px;
 text-align: left;
 padding: 10px 10px;
 text-decoration: none;
 background-color: #C0C0C0;
}

ul.newclass li a:hover {
 background-color: #FFD700;
}

是否有可能通过任何奇怪的诡计来实例化<ul class="newclass"> <li><a class="" href="index.html">Home</a></li> <li><a href="mypage1.html">Partners</a></li> </ul> <ul> <li><a class="" href="index1.html">Main Page</a></li> <li><a href="mypage2.html">Partners2</a></li> </ul>类型的对象(在堆栈上(可能不是)或堆上(可能是?)),或者template <class T> class object { public: using type = T; object() = delete; object(const object&) = delete; object(object&&) = delete; object& operator=(const object&) = delete; object& operator=(object&&) = delete; ~object() = delete; private: type value = 0; }; 是不可能的以任何可以想象的(形成良好且定义明确的行为)object<int>程序存在?

附录:首先我们考虑非格式的NDR程序/非未定义的行为。当且仅当可能存在格式错误的NDR程序/未定义的行为程序时,您可以用这样的程序说明答案。

3 个答案:

答案 0 :(得分:4)

不,不能。来自[basic.life]

  

[...]类型为T的对象的生命周期始于:

     
      
  • 获取具有T类型的正确对齐和大小的存储,

  •   
  • 如果对象具有非空的初始化,则其初始化完成,

  •   

因此必须执行初始化。然后我们查看all the possible initializations

  1. 如果初始值设定项为{...},则为list-initialized

    • 该类是非聚合的,因此不能是aggregate-initialized
    • 该类没有默认构造函数,因此{}无法对其进行值初始化
    • 该类可以由{x}直接初始化或复制初始化,()通过重载解析调用构造函数
  2. 如果初始值设定项为T x = T(T());,则表示值已初始化

  3. 如果初始化程序是相同的cv-unqualified类型,则初始化程序的初始化程序表达式将用作初始化程序

    • 也就是说,x只是默认初始化ngModel,没有副本
  4. 如果没有初始值设定项,则默认初始化

  5. 否则将考虑使用重载解析来调用构造函数。

  6. 在这种情况下,值初始化是默认初始化对象。

  7. 默认初始化在这种情况下调用默认构造函数。

  8. 如果仔细观察,此列表中只有一种方法可以初始化对象,即调用构造函数。由于我们删除了所有构造函数,因此无法初始化对象。

答案 1 :(得分:1)

我不是声称这是一个答案(我不是语言律师),只是发布了n4659的一些调查结果:

  

11.6.20:即使没有为初始化调用对象类的构造函数,也认为构造了初始化已完成的对象。 [注意:这样的对象可能已经过值初始化或   由聚合初始化(11.6.1)或继承的构造函数(15.6.3)初始化。 - 后注]

从说明中提到的3个选项中,只有第一个适用:

  

11.6.8:对于值初始化类型为T的对象意味着...(8.1) - 如果T是(可能是cv限定的)类类型(第12条),则为no默认构造函数(15.1)用户提供或删除的默认构造函数,然后对象默认初始化;

由于删除了默认构造函数:

  

11.6.7:对于 default-initialize ,类型为T的对象意味着......(7.1) - 如果T是(可能是cv限定的)类类型(第12条),构造函数是考虑。枚举适用的构造函数(16.3.1.3),通过重载解析(16.3)选择初始化函数()的最佳构造函数。 这样选择的构造函数被称为,带有一个空参数列表,用于初始化对象。

由于没有可以调用的构造函数,我认为无法构造类object的实例。

答案 2 :(得分:-1)

规则很明确,此对象无法正确初始化。

因为这是要求的,所以为你的类创建一个缓冲区,并小心使用它。

template< typename T >
class object_wrapper
{
    std::byte buffer[ sizeof( T ) ];

public:
    auto& inner() { return *reinterpret_cast< T* >( buffer ); }
};

以下是一个例子:

int main()
{
    //object< int > o; // impossible

    object_wrapper< object< int > > ow; // wrap the object

    object< int >& o( ow.inner() );     // possible

    o.some_foo();

}