系统地重载r值参考是一个好的模式吗?

时间:2016-07-10 07:09:06

标签: c++11 overloading rvalue-reference

我有一个与({C ++ 11版本的)std::ostream非常相似的类,我可以流式传输许多不同的(不相关的)类型。

class mystream{...some implementation...};

要定义的典型功能是

mystream& operator<<(mystream& ms, type1 const& t1){...}

mystream& operator<<(mystream& ms, type2 const& t2){...}

然而,(就像使用C ++ 11&#9的流一样)我想在流程上进行构建。例如:

mystream{} << t1;

为了能够做到这一点,我为每种类型的l值引用重载:

mystream& operator<<(mystream&& ms, type1 const& t1){
   return ms << t1; // this calls the l-value version
}

代码并不复杂,但它是重复的,因为我必须为所涉及的所有类型执行此操作。由于此类的性质,使用引用和l值引用是有意义的。

问题是这是否是正确的做法?我应该为每种类型写两个函数吗?这是一个好模式吗?

次要问题:当然,我可以在适当的时候做一些模板魔术来接受l值参考,但我不知道这是否是推荐路径。

三元问题:函数应该返回mystream&(如上所述)还是mystream&&

这是示例代码:

class A{};
class B{};

class mystream{};

mystream& operator<<(mystream& ms, A const& a){return ms;} // (1)
mystream& operator<<(mystream& ms, B const& b){return ms;} // (2)

mystream& operator<<(mystream&& ms, A const& a){return ms; /*ms << a;*/} // (3)
mystream& operator<<(mystream&& ms, B const& b){return ms; /*ms << a;*/} // (4)

int main(){

    mystream ms;
    ms << A{};
    ms << B{};

    mystream{} << A{}; // ok only if line (3) is defined
    mystream{} << B{}; // ok only if line (4) is defined

}

如果我对第(3)行进行注释,则错误信息为

fatal error: invalid operands to binary expression ('mystream' and 'A')
        mystream{} << A{}; // ok only if line (3) is defined
        ~~~~~~~~~~ ^  ~~~
././random.hpp:146:11: note: candidate function not viable: expects an l-value for 1st argument
mystream& operator<<(mystream& ms, A const& a){return ms;} // (1)

如果我评论第(1)行,则反过来

fatal error: invalid operands to binary expression ('mystream' and 'A')
        ms << A{};
        ~~ ^  ~~~
././random.hpp:149:11: note: candidate function not viable: no known conversion from 'mystream' to 'mystream &&' for 1st argument
mystream& operator<<(mystream&& ms, A const& a){return ms; /*ms << a;*/} // (3)

1 个答案:

答案 0 :(得分:2)

C ++定义了一个带有ostream右值引用的函数模板:

template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os, 
                                            const T& value );

它调用适当的插入运算符。因此,您应该只定义

template <typename X>
mystream& operator<< (mystream&& ms, const X& x)
{
    ms << x;
    return ms;
}