通过在ISO C ++标准的std ::元组的默认构造函数描述困惑(Confused by defa

2019-06-26 03:47发布

该标准说std::tuple具有以下成员函数

constexpr tuple();
explicit tuple(const Types&...);

可有人请解释什么是应该发生的std::tuple<>

Answer 1:

我相信这是标准的一个小错误。 显然,当所述Types参数包是空的,这两个构造函数调用是等效的,并且不能被重载(参照C ++ 11第13部分)。 (另外请注意,使用构造Types是不是一个成员模板要么--IF它,那么这将是一个合法的过载)。

换句话说,这个代码不会编译:

template <typename... Types>
struct Test
{
  constexpr Test() {}
  explicit Test(Types const&...) { /* etc. */ }
};

int main()
{
  Test<> a;
  Test<int> b;
}

例如,克++ V4.8快照输出:

tt.cxx: In instantiation of ‘struct Test<>’:
tt.cxx:10:10:   required from here
tt.cxx:5:12: error: ‘Test<Types>::Test(const Types& ...) [with Types = {}]’ cannot be overloaded
   explicit Test(Types const&...) { /* etc. */ }
            ^
tt.cxx:4:13: error: with ‘constexpr Test<Types>::Test() [with Types = {}]’
   constexpr Test() {}
             ^

这可以是固定的,通过使用偏特:

template <typename... Types>
struct Test
{
  constexpr Test() {} // default construct all elements
  explicit Test(Types const&...) { /* etc. */ }
  // and all other member definitions
};

template <>
struct Test<>
{
  constexpr Test() {}
  // and any other member definitions that make sense with no types
};

int main()
{
  Test<> a;
  Test<int> b;
}

这将正确编译。

它出现的标准需要一个constexpr默认的构造函数,是因为这样std::tuple<> var; 可以写成代替书写std::tuple<> var();std::tuple<> var{}; 因为使用的explicit与其他构造。 不幸的是,它的定义std::tuple没有为大小为0的元组工作。 标准确实允许这样在第20.4.2.7(关系运算符)不过,“对于任何两个零长度的元组,[...]。” 哎呀! :-)



Answer 2:

我想在标准中给出的定义应该是伪代码。 这与很多标准的定义的情况下; 它包含了口头方式发出通知,但只与像花样可满足几个要求enable_if 。 这似乎是一个例子,其中的C ++ - 试图实例化这样一个空的元组(或者它可能只是一个遗漏),当像伪代码符号实际上导致非法C ++。

既stdlibc ++和的libc ++具有零元素的元组的显式特。 例如,在stdlibc ++:

  // Explicit specialization, zero-element tuple.
  template<>  
    class tuple<>
    {
    public:
      void swap(tuple&) noexcept { /* no-op */ }
    };

与隐式定义明确的默认构造函数。

的libc ++没有显式声明的参数的默认构造函数。 据推测,该模板构造函数,然后选择作为非空元组的默认构造函数。

有趣的是,这两个库不同意空的元组有什么成员。 例如,以下与libc中++编译,但不是的libstdc ++:

#include <tuple>
#include <memory>

int main() {
  std::tuple<> t(std::allocator_arg, std::allocator<int>());
}


Answer 3:

乍一看,模糊只在无关紧要的地方就是所谓的点,然后你有正常的重载解析。



文章来源: Confused by default constructor description of std::tuple in the ISO C++ Standard