如何使用c ++(0x)中的多个返回值进行初始化

BCo*_*tes 11 c++ boost tuples c++11

tuple 在boost和TR1/c ++ 0x中提供了一个方便的(对于函数的编写者)方法从函数返回两个值 - 但它似乎损坏了调用者语言的一个主要特征:简单使用的能力初始化变量的函数:

T happy();
const auto meaningful_name(happy()); // RVO means no excess copies
Run Code Online (Sandbox Code Playgroud)

但对于:

tuple<T,U> sad();
Run Code Online (Sandbox Code Playgroud)

我们要么放弃为返回值选择有意义的名称的能力,要么在get<n>()任何地方使用:

const auto two_unrelated_things(sad());
Run Code Online (Sandbox Code Playgroud)

或临时:

const auto unwanted_named_temporary(sad());
const auto one_name(get<0>(unwanted_named_temporary));
const auto two_name(get<1>(unwanted_named_temporary));
Run Code Online (Sandbox Code Playgroud)

或从初始化切换到赋值,仅在类型可分配时有效,并且中断auto:

tuple_element<0, decltype(sad())>::type one_mutable; // there might be a less
tuple_element<1, decltype(sad())>::type two_mutable; // verbose way
tie(one_mutable,two_mutable) = sad();
Run Code Online (Sandbox Code Playgroud)

或者对当地​​班级做一些不自然的事情:

const struct ugh { 
  ugh( decltype(sad()) rhs ) : one_name(get<0>(rhs)), two_name(get<1>(rhs)) {}
  const tuple_element<0, decltype(sad())>::type one_name;
  const tuple_element<1, decltype(sad())>::type two_name;
} stuff(sad()); // at least we avoid the temporary and get initialization
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?我正在使用上面的VC10兼容结构,是否有完整的c ++ 0x或boost帮助?

理想情况下它会:

  • 允许我使用初始化,而不仅仅是赋值
  • 调用者选择返回变量的名称
  • 不要制作额外的副本
  • 适用于堆栈变量和类成员
  • 可能是一个很大的疯狂模板库,但对于调用者和函数编写者来说,它具有合理的语法

Den*_*ose 2

std::tuple<Type1, Type2> returnValue = sad();
Type1& first = std::get<0>(returnValue);
Type2& second = std::get<1>(returnValue);
Run Code Online (Sandbox Code Playgroud)

我不确定你的第四个项目符号是什么意思,但这满足了其余的要求。

*编辑:根据您上面的评论,我明白了您第四个项目符号的含义。

struct Object {
    Object(const std::tuple<Type1, Type2>& t) : value(t) { }
    Type1& First() { return std::get<0>(value); }
    Type2& second() { return std::get<1>(value); }
private:
    std::tuple<Type1, Type2> value;
}
Run Code Online (Sandbox Code Playgroud)

根据需要修改。

std::tuple如果返回的值非常不相关,以至于您必须将它们分开才能合理使用,您也可以根本不使用它们。多年来,人们一直通过struct使用合理命名的字段来返回 s,或者通过接受输出的引用参数来实现。

顺便说一句,你似乎爱上了auto。别这样。这是一个很棒的功能,但这不是应该使用的方式。如果您不时不时指定类型,您的代码最终将难以辨认。