boost :: variant和operator <<重载

Gab*_*iel 2 operator-overloading ostream boost-variant c++11

我想测试一个简单的事情,如下所示:

#include <iostream>
#include <boost/variant.hpp>

template<typename T1,typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1,T2>& dt){
    os << dt.first << dt.second;
    return os;
}



int main(){

   boost::variant<int, std::pair<int,int>, bool> v;
   v = std::pair<int,int>(3,3);
   std::cout << v << std::endl;

}
Run Code Online (Sandbox Code Playgroud)

这实际上应该有效,因为对于普通类型,int, double等等,它会编译. boost::variant有一个打印机vistor,它在内部使用它来输出内容到流.实际上这无法编译,但我真的不知道这个问题:

代码在这里失败:在variant_io.hpp中

template <typename OStream>
class printer
    : public boost::static_visitor<>
{
private: // representation

    OStream& out_;

public: // structors

    explicit printer(OStream& out)
        : out_( out )
    {
    }

public: // visitor interface

    template <typename T>
    void operator()(const T& operand) const
    {
        out_ << operand;  // HEEEEEEERRRRREE!!!!!!!!!!!!
    }

private:
    printer& operator=(const printer&);

};
Run Code Online (Sandbox Code Playgroud)

随着消息:

/usr/local/include/boost/variant/detail/variant_io.hpp|64|error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&'
Run Code Online (Sandbox Code Playgroud)

有人知道我做错了什么,为什么?

非常感谢!

Seb*_*edl 5

很可能它没有找到你的重载operator <<,然后在尝试匹配其他一些重载时感到困惑,导致你得到的任何消息.

你做错了什么:你在全局命名空间中重载了流操作符而不是在定义右侧类的命名空间中,因此ADL找不到它.

不幸的是,试图为标准类重载流操作符是一个注定要失败的练习.你实际上不能这样做.我不确定是否有针对它的明确规则.但是,如果您必须将操作符放在命名空间std中以便ADL可以正确查找,那么您违反了无法将自己的内容添加到命名空间的规则,std除非在非常特殊的情况下,这不是其中之一.

底线是std::pair没有流操作符,并且不可能合法地添加有用的通用操作符.如果其中一个参数是您自己定义的类,则可以为特定实例添加一个; 在这种情况下,操作符需要放在您自己的类旁边.