在C++ 11中从函数返回元组的最佳方法是什么?

Gia*_*cci 25 c++ c++11 stdtuple

我想从函数中返回一些值,我想将它打包在一个元组中.所以我有两种功能声明的可能性:

std::tuple<bool, string, int> f()
{
  ...
  return std::make_tuple(false, "home", 0);
}
Run Code Online (Sandbox Code Playgroud)

std::tuple<bool, string, int> f()
{
  ...
  return std::forward_as_tuple(false, "home", 0);
}
Run Code Online (Sandbox Code Playgroud)

这些功能是等价的?在您喜欢的这些功能之间?

And*_*owl 21

std::forward_as_tuple()创建一个引用元组.既然你还是要回来了tuple<bool, string, int>,在这种情况下两者最终是等价的,但我认为第一种方法更清楚 - forward_as_tuple()当你不转发任何东西时使用是令人困惑的.

另外,正如Sebastian Redl在评论中所提到的,make_tuple()将允许编译器执行复制省略 - 根据C++ 11标准的第12.8/31段而forward_tuple()不会(因为它返回的内容与函数的类型不同)返回类型).

  • 而且,效率更高.第一种方法可能使用复制省略(如果你在std :: string构造函数调用中包装字符串文字),第二种方式不能,因为它不是普通的副本. (4认同)

pep*_*ico 5

我更喜欢,

std::tuple<bool, std::string, int> f()
{
  ...
  return { false, "home", 0 };
}
Run Code Online (Sandbox Code Playgroud)

编辑1

上面的代码实际上是在clang/libc ++ trunk下编译的.正如@AndyProwl在注释部分中评论的那样,这不应该是因为std :: tuple构造函数是显式的,并且通过initial-list语法返回是在复制初始化上下文中,因此复制列表初始化,当匹配显式构造函数时失败.

我不知道clang/libc ++传递的原因,我想它是libc ++中的一个bug.无论如何,对于元组来说,这是不可能的.

我想我总体上意识到这对我来说是多么悲伤(对我而言).我已经习惯了这种语法,但是必须事先知道返回类型是否随时都包含一个显式构造函数才能生效.

编辑2

这确实是一个libc ++扩展,有关更多信息,请查看Howard Hinnant在这里回答:https://stackoverflow.com/a/14963014 .

它目前也在libc ++错误列表中打开:http://llvm.org/bugs/show_bug.cgi?id = 15299.

这是相关的提议:DanielKrügler,改进对和元组.

简而言之,这就是libc ++所发生的事情:

#include <tuple>
#include <string>

struct S
{
    explicit S(int) {}
};

int main()
{
    std::tuple<int, std::string> t1 = { 1, "hello" }; // ok
    std::tuple<std::string> t2      = "hello";        // ok
    std::tuple<int, S> t3           = { 1, 1 };       // fail: an *element* is to be constructed explicitly
}
Run Code Online (Sandbox Code Playgroud)

  • 我也更喜欢它,但是`std :: tuple`有一个显式的构造函数,这意味着上面的代码不能编译 (3认同)
  • @AndyProwl让我们希望有人将[N3452](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3452.pdf)纳入未来的标准. (3认同)