C++ 如何在c++;(0x)

C++ 如何在c++;(0x),c++,boost,c++11,tuples,C++,Boost,C++11,Tuples,boost和TR1/c++0x中的tuple提供了一种方便的(对于函数编写者而言)方法来从函数返回两个值,但是这似乎损害了调用者语言的一个主要功能:仅使用函数初始化变量的能力: T happy(); const auto meaningful_name(happy()); // RVO means no excess copies 但对于: tuple<T,U> sad(); 或临时: const auto unwanted_named_temporary(sad()); con

boost和TR1/c++0x中的
tuple
提供了一种方便的(对于函数编写者而言)方法来从函数返回两个值,但是这似乎损害了调用者语言的一个主要功能:仅使用函数初始化变量的能力:

T happy();
const auto meaningful_name(happy()); // RVO means no excess copies
但对于:

tuple<T,U> sad();
或临时:

const auto unwanted_named_temporary(sad());
const auto one_name(get<0>(unwanted_named_temporary));
const auto two_name(get<1>(unwanted_named_temporary));
或者对本地类执行一些不自然的操作:

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
const-struct-ugh{
ugh(decltype(sad())rhs):一个名字(get(rhs)),两个名字(get(rhs)){}
常量元组元素::键入一个\u名称;
常量元组元素::键入两个\u名称;
}东西(sad());//至少我们避免了临时性的初始化
有更好的办法吗?我正在使用上面的VC10兼容结构,完整的c++0x或boost中有什么帮助吗

理想的情况是:

  • 允许我使用初始化,而不仅仅是赋值
  • 让调用方选择返回变量的名称
  • 不做额外的拷贝
  • 适用于堆栈变量和类成员
  • 可能是一个大的疯狂的模板库,但对于调用方和函数编写器来说,它的语法是合理的
std::tuple returnValue=sad();
类型1&first=std::get(返回值);
Type2&second=std::get(返回值);
我不知道你的第四颗子弹是什么意思,但这满足了所有其他人

*编辑:根据你上面的评论,我明白了你说的第四个子弹是什么意思

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;
}
struct对象{
对象(const std::tuple&t):值(t){}
Type1&First(){return std::get(value);}
Type2&second(){return std::get(value);}
私人:
std::元组值;
}
根据需要修改

如果返回的值非常不相关,您必须将它们拆分,以便合理使用,那么您也可以根本不使用
std::tuple
。多年来,人们通过返回带有合理命名字段的
struct
s,或者通过接受输出的引用参数来获取数据


另外,你似乎爱上了
auto
。别担心。这是一个很好的特性,但这不是它应该使用的方式。如果您不经常指定类型,您的代码将变得难以辨认。

有趣的问题,尽管我不知道如何在一个表达式中定义不同类型的变量。-我认为,如果您将命名变量更改为引用(避免复制),那么“或创建临时”选项可能是可以的。关于引用,这是一个很好的观点——我认为这是堆栈变量的解决方案。我试着在一个类中做同样的事情:类C{public:C()sr(sad()),一个(get(sr)),两个(get(sr)){}常量T&one;常量U&two;private:tuple sr;}但在VC10中,C看起来比元组大两个指针,这不是什么大问题,但有点蹩脚——编译器认识到引用是别名而不在实例中为它们分配空间难道不合法吗?这不就是为什么指向引用的指针首先是非法的吗?对于一个类,如果数据存储为元组,您可以只提供命名的访问器方法,这些方法调用相应的
get
。我怀疑是否会有一个基于“疯狂模板”的解决方案,因为核心语言似乎根本不支持您的要求。也许你可以减少你必须用宏输入的字符数……我在起草答案时,不知怎的错过了注释。一旦注意到,我扩展了我的答案,只是想再次写下你已经有过的东西。我想,跟我来吧。当我想到“班级成员”这一点时,这是一种你可以删除所有副本的情况吗?我认为在任何情况下,您都将至少复制一次
value
,这显然需要至少复制一次其成员。因此,您可能还不如直接存储值,而完全忘记存储元组。我同意在不合适的时候不使用
std::tuple
——我只是担心它会变得惯用,使代码变得不易理解,并且充满
get(sometuple)
,也就是说,看起来我太担心额外的副本了:
tie(a,b)=sad()
当sad()返回make\u tuple(…)时,构造函数中的sad()成功地删除了所有元组成员的副本。也许教训是“
const
数据成员很麻烦”。@bcoates:关于元组的误用和过度使用。当标准库将范围表示为
pair
时,它本身就有点内疚。OTOH,boost采用了一种更好的替代方法:
iterator\u range
,使用
begin()
end()
方法。范围不是一个抽象的对,
第一个
第二个
确实有具体的含义我认为,在非泛型代码中,人们不应该非常喜欢元组。
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
std::tuple<Type1, Type2> returnValue = sad();
Type1& first = std::get<0>(returnValue);
Type2& second = std::get<1>(returnValue);
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;
}