在ISO C++标准中由std :: tuple的默认构造函数描述混淆

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<>什么吗?

Phi*_*ipp 6

我想标准中给出的定义应该是伪代码.标准中的许多定义就是这种情况; 它包含了一些口头上给出的要求,但只有像这样的技巧才能满足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)

  • 另一个标准引用(§20.4.2.7/ 5):"对于任何两个*零长度的元组*e和f,e <f返回false." (3认同)

Pau*_*ney 3

我认为这是标准中的一个小错误。显然,当Types参数包为空时,两个构造函数调用是等效的并且不能重载(参见C++11第13节)。(进一步注意,构造函数使用Types也不是成员模板——如果是,那么它将是合法的重载。)。

\n\n

换句话说,这段代码将无法编译:

\n\n
template <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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

例如,g++ v4.8 快照输出:

\n\n
tt.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             ^\n
Run Code Online (Sandbox Code Playgroud)\n\n

这可以通过使用部分特化来解决:

\n\n
template <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}\n
Run 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 节(关系运算符)中确实允许这样的操作,“对于任何两个零长度元组,[...]”。哎呀!:-)

\n