被删除的构造函数是否“可访问”?

时间:2013-12-28 15:20:59

标签: c++ c++11 language-lawyer

关于已删除的移动构造函数的this question上的已删除答案引用cppreference.com as saying,只要移动构造函数是“可访问的”,is_move_constructible特征就应该成功,即使它不是“可用的” ”

标准实际上要求参数类型的移动构造是格式良好的,所以答案并不完全正确。

现在,该标准重复使用与构造函数相关的术语“可访问”,指的是实际的可构造性。例如:

  

[C++11 8.5/6]:默认初始化T类型的对象意味着:

     
      
  • 如果T是(可能是 cv-qualified )类类型(第9条),则调用T的默认构造函数(初始化为如果T没有可访问的默认构造函数);
  • ,则格式错误   
  • 如果T是数组类型,则每个元素都是默认初始化;
  •   
  • 否则,不执行初始化。
  •   
     

如果程序要求对const限定类型T的对象进行默认初始化,则T应为具有用户提供的默认构造函数的类类型。

但是,我无法在标准中的任何地方找到明确说明delete d,显式定义的构造函数是否“可访问”。

一个不同的[非规范]引用似乎表明delete d-ness和可访问性是正交的:

  

[C++11: 12.2/1]: [..] [注意:即使没有调用析构函数或复制/移动构造函数,所有语义限制,例如可访问性(第11条)和是否删除功能(8.4.3)。 [..]

  • 我错过了一段文章吗?
  • 如果没有,是否应更正cppreference.com页面?你能建议更好的措辞吗?
  • 标准是否应该更清楚这一点?

2 个答案:

答案 0 :(得分:12)

我不想解决cppreference网站所说的内容,但就标准而言,可构造性并未根据“可访问的构造函数”进行定义。相反,主要定义是is_constructible的定义,即(C ++ 11,20.9.4.3/6):

is_constructible<T, Args...>
     

应满意   当且仅当以下变量定义适用于某些发明变量t

T t(create<Args>()...);
     

执行访问检查,就像在与T和任何Args无关的上下文中一样。只考虑变量初始化的直接上下文的有效性。

因此,最后一行代码中假设表达的良构性是构造性特征的定义特征。这与使用删除函数导致格式错误的程序的条款密切配合。

答案 1 :(得分:9)

从问题的第二个引用开始,我说可访问性不受delete dness的影响,并且第一个引用实际上不 涵盖了这样的构造函数可能是delete d。

此方案由delete的定义中的某种“包罗万象”要求涵盖:

  

[C++11: 8.4.3/2]:隐式或显式地引用已删除函数的程序,除了声明它之外,都是格式错误的。 [注意:这包括隐式或显式调用函数并形成指向函数的指针或指向成员的指针。它甚至适用于未进行潜在评估的表达式中的引用。如果函数重载,则仅在通过重载决策选择函数时才引用它。 -end note]

因此,cppreference.com可能会注意到还有一个适用于is_move_constructible特征的标准,而不仅仅是移动构造函数是否可访问。这里还有一个问题,那就是CopyConstructible也可以满足is_move_constructible ,所以即使是移动构造函数本身也不是绝对必要的。

这一切都提出了另一个有趣的观点,即{{1}}的任何可能实现都必须“引用”已删除的移动构造函数,这会导致程序格式错误,如上面引用中所述。尽管如此,我认为使用SFINAE技巧可以避免实际上变形。


“一个没有移动ctor的类型,但有一个复制器是可移动构造的(可从rvalue构造)。” - MoveConstructible