检查引用元组是否为默认构造时出错

时间:2015-07-15 14:56:31

标签: c++ c++11 std c++14 stdtuple

使用g ++ - 5我得到以下输出

#include <type_traits>
#include <tuple>
int main()
{
  bool b;
  b = std::is_default_constructible<int>::value; //Compiles, returns true
  b = std::is_default_constructible<int&>::value; //Compiles, returns false
  b = std::is_default_constructible< std::tuple<int> >::value; //Compiles, returns true
  b = std::is_default_constructible< std::tuple<int&> >::value; //Does not compile
}

这是is_default_constructible实施中的错误吗?

错误消息是一个以下列结尾的长堆栈列表:

/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/../../../../include/c++/5.1.0/tuple:105:9: error: reference to type 'int' requires an initializer
  : _M_head_impl() { }

1 个答案:

答案 0 :(得分:6)

<{1}}中的错误 。该类型特征仅需要检查默认构造的直接上下文,它不必深入评估任何成员初始化器。这种限制可能是因为它可以通过使用SFINAE在没有专用编译器魔法的情况下实现。 (见[meta.unary.prop],特别是p7)。

如果元素类型不能默认构造,则is_default_constructibletuple默认构造函数不需要在直接上下文中失败(SFINAE友好)。这已由LWG 2367解决,它为pair默认构造函数引入了以下SFINAE要求:

  

备注:此构造函数不应参与重载解析   除非tuple适用于所有is_default_constructible<Ti>::value。 [...]

有了这个额外的要求,元组的默认构造必须以SFINAE友好的方式失败,这样i现在适用于is_default_constructible如果元素未能在直接上下文中默认构造(参考类型就是这种情况)。

LWG 2367目前处于 Ready 状态;提议的决议尚未(尚未)纳入github草案。

[ - 这部分仍在考虑之中

Yakk在评论中提出了一个重点:为什么tuple必须深度实例化成员初始值设定项?

据我所知,这与is_default_constructible的默认构造函数的条件constexpr'iveness 有关。 tuple导致默认构造函数的实例化。它只需要实例化声明,以确定是否可以在立即上下文中无故障地调用此构造函数。但是,声明的实例化需要确定is_default_constructible'iveness,这会导致构造函数定义的实例化。

已标记为constexpr的类模板的成员函数(或构造函数)仅有条件constexpr:只有那些类模板实例化的成员函数才会constexpr身体没有违反constexpr限制。这需要为构造函数实例化构造函数的主体,以便检查是否允许在constexpr函数内使用成员初始值设定项。考虑:

constexpr

在实例化struct nonconstexpr { nonconstexpr() { std::cout << "runtime\n"; } }; struct isconstexpr { constexpr isconstexpr() {} }; template<typename T> struct wrapper { T t; constexpr wrapper() : t() {} }; 的默认ctor时,编译器必须实例化成员初始值设定项,以确定此实例化是否为wrapper

constexpr的情况下,这会导致某个成员初始化程序的实例化,它尝试对初始化引用元组叶(数据成员)进行值初始化。这是一个错误,它不会发生在默认构造函数的原始实例化的直接上下文中。因此,这是一个很难的错误而不是直接背景下的替代失败。

- ]

这一部分对我来说并不完全清楚,因为CWG 1358基本上使所有实例化std::tuple,无论它们是否真正符合标准。事实上,gcc 6.0并没有编译以下示例,而gcc 5.1和clang 3.7拒绝它:

constexpr
CWG 1358还告诉我们为什么两种方法之间的区别 - 条件constexpr和constexpr尽管有违规行为 - 很重要:

  

在讨论第1581期时是否出现了问题   方法 - 使constexpr功能模板专业化   或类模板的成员函数仍然constexpr但无法   在一个恒定的上下文中调用 - 是正确的。这意味着   类类型可能被归类为文字,但不能   在编译时实例化。因此返回此问题   “审查”状态,以便进一步考虑这个问题。

对于libc ++,有一个bug #21157,它已于2014-10-15解决并出现在clang3.6分支中。对于libstdc ++,似乎没有错误报告;该问题已在combined commit on 2015-06-30中修复,该N4387 - Improving Pair and Tuple (Revision 3)也实现{{3}},目前似乎没有出现在任何gcc5分支中。