26

我想从一个函数返回一些值,我想把它打包成一个元组。所以我有两种可能的函数声明:

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

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

这些功能是等价的吗?在这些功能之间,您更喜欢哪个?

4

2 回答 2

21

std::forward_as_tuple()创建一个引用元组。由于您无论如何都返回 a ,因此在这种情况下tuple<bool, string, int>两者最终是等效的,但我认为第一种方法更清晰 -在您不转发任何内容时使用会令人困惑。forward_as_tuple()

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

于 2013-05-23T11:56:04.770 回答
7

我更喜欢,

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

编辑 1

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

我不知道 clang/libc++ 通过的原因,我想它是 libc++ 中的一个错误。无论如何,对于元组无法做到这一点很遗憾......

我想我意识到(对我来说,最后)它是多么悲伤,一般来说。我已经习惯了这种语法,但是人们不得不事先知道返回类型是否包含一个显式的构造函数以便它工作。

编辑 2

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

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

这是相关的建议:Daniel Krü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
}
于 2013-05-23T12:02:20.457 回答