首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >被C++标准中std::tuple的默认构造函数描述弄糊涂了

被C++标准中std::tuple的默认构造函数描述弄糊涂了
EN

Stack Overflow用户
提问于 2012-07-09 03:34:49
回答 3查看 2.7K关注 0票数 18

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

代码语言:javascript
复制
constexpr tuple();
explicit tuple(const Types&...);

有人能解释一下std::tuple<>会发生什么吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-09 04:39:17

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

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

代码语言:javascript
复制
template <typename... Types>
struct Test
{
  constexpr Test() {}
  explicit Test(Types const&...) { /* etc. */ }
};

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

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

代码语言:javascript
复制
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() {}
             ^

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

代码语言:javascript
复制
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节(关系运算符)中确实允许这样做,“对于任何两个长度为零的元组,...”。哦!:-)

票数 2
EN

Stack Overflow用户

发布于 2012-07-09 04:00:59

我猜标准中给出的定义应该是伪代码。标准中的许多定义就是这种情况;它包含几个口头给出的要求,但只能通过enable_if这样的技巧才能满足。这似乎是一个例子,当试图实例化这样的空元组时,类似C++的伪代码表示法实际上可能导致非法的C++(或者它可能只是遗漏)。

stdlibc++和libc++都对零元素元组进行了显式专门化。例如,在stdlibc++中:

代码语言:javascript
复制
  // Explicit specialization, zero-element tuple.
  template<>  
    class tuple<>
    {
    public:
      void swap(tuple&) noexcept { /* no-op */ }
    };

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

Libc++没有显式声明无参数的默认构造函数。然后可能会选择模板化的构造函数作为非空元组的默认构造函数。

有趣的是,这两个库在空元组包含哪些成员的问题上存在分歧。例如,以下代码使用libc++编译,但不使用libstdc++编译:

代码语言:javascript
复制
#include <tuple>
#include <memory>

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

Stack Overflow用户

发布于 2012-07-09 03:52:48

乍一看,模糊性只在被调用的地方才重要,然后你就有了正常的重载解决方案。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11386042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档