Joh*_*itb 18 c++ language-lawyer c++11 stdtuple
标准表示std::tuple具有以下成员功能
constexpr tuple();
explicit tuple(const Types&...);
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下应该发生std::tuple<>什么吗?
我想标准中给出的定义应该是伪代码.标准中的许多定义就是这种情况; 它包含了一些口头上给出的要求,但只有像这样的技巧才能满足enable_if.这似乎是一个例子,在尝试实例化这样一个空元组时,类似C++的伪代码符号实际上会导致非法的C++(或者它可能只是一个遗漏).
stdlibc ++和libc ++都对零元素元组有明确的特化.例如,在stdlibc ++中:
// Explicit specialization, zero-element tuple.
template<>
class tuple<>
{
public:
void swap(tuple&) noexcept { /* no-op */ }
};
Run Code Online (Sandbox Code Playgroud)
使用隐式定义的明确默认构造函数.
Libc ++没有显式声明无参数的默认构造函数.据推测,模板化的构造函数然后被选为非空元组的默认构造函数.
有趣的是,这两个图书馆不同意空元组的成员.例如,以下用libc ++编译,但不用libstdc ++编译:
#include <tuple>
#include <memory>
int main() {
std::tuple<> t(std::allocator_arg, std::allocator<int>());
}
Run Code Online (Sandbox Code Playgroud)
我认为这是标准中的一个小错误。显然,当Types参数包为空时,两个构造函数调用是等效的并且不能重载(参见C++11第13节)。(进一步注意,构造函数使用Types也不是成员模板——如果是,那么它将是合法的重载。)。
换句话说,这段代码将无法编译:
\n\ntemplate <typename... Types>\nstruct Test\n{\n constexpr Test() {}\n explicit Test(Types const&...) { /* etc. */ }\n};\n\nint main()\n{\n Test<> a;\n Test<int> b;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n例如,g++ v4.8 快照输出:
\n\ntt.cxx: In instantiation of \xe2\x80\x98struct Test<>\xe2\x80\x99:\ntt.cxx:10:10: required from here\ntt.cxx:5:12: error: \xe2\x80\x98Test<Types>::Test(const Types& ...) [with Types = {}]\xe2\x80\x99 cannot be overloaded\n explicit Test(Types const&...) { /* etc. */ }\n ^\ntt.cxx:4:13: error: with \xe2\x80\x98constexpr Test<Types>::Test() [with Types = {}]\xe2\x80\x99\n constexpr Test() {}\n ^\nRun Code Online (Sandbox Code Playgroud)\n\n这可以通过使用部分特化来解决:
\n\ntemplate <typename... Types>\nstruct Test\n{\n constexpr Test() {} // default construct all elements\n explicit Test(Types const&...) { /* etc. */ }\n // and all other member definitions\n};\n\ntemplate <>\nstruct Test<>\n{\n constexpr Test() {}\n // and any other member definitions that make sense with no types\n};\n\nint main()\n{\n Test<> a;\n Test<int> b;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这将正确编译。
\n\n看来标准想要一个constexpr默认构造函数,以便std::tuple<> var;可以编写而不是编写std::tuple<> var();或因为与其他构造函数std::tuple<> var{};一起使用。explicit不幸的是,它的定义std::tuple不适用于大小为零的元组。标准在第 20.4.2.7 节(关系运算符)中确实允许这样的操作,“对于任何两个零长度元组,[...]”。哎呀!:-)