使用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() { }
答案 0 :(得分:6)
<{1}}中的错误 。该类型特征仅需要检查默认构造的直接上下文,它不必深入评估任何成员初始化器。这种限制可能是因为它可以通过使用SFINAE在没有专用编译器魔法的情况下实现。 (见[meta.unary.prop],特别是p7)。
如果元素类型不能默认构造,则is_default_constructible
和tuple
默认构造函数不需要在直接上下文中失败(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分支中。