ADL无法使用适当的限定符为用户定义的类型定位流操作符

时间:2012-05-14 20:55:29

标签: c++ boost boost-variant stream-operators

我正在使用Visual Studio 2010在Microsoft Windows 7上编译x64服务,使用Boost variant之类的内容:

namespace my_ns
{
    typedef struct {} empty_t;
    typedef std::pair<size_t, std::shared_ptr<char>> string_t;
    typedef boost::variant<empty_t, double, long, string_t> variant_t;
    typedef std::map<unsigned short, variant_t> variant_map_t;
}

我摆脱那个string_t并用std :: string替换它的那天是我买老板和团队甜甜圈的那一天。但这不是我们在这里的原因......

如果类型具有重载,则Boost变体支持其包含类型的流运算符。所以我有:

namespace my_ns
{
    std::ostream &operator<<(std::ostream &, const empty_t &);
    std::ostream &operator<<(std::ostream &, const string_t &);
}

然而,我受到错误信息的困扰:

error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const T3' (or there is no acceptable conversion)

T3指的是string_t。

产生错误的违规代码存在于以下上下文中。它是冗长的,所以你,读者,有相关的背景信息:

namespace my_ns
{
    void Widget::public_method(std::ostringstream &os) const
    {
        //variant_map_t Widget::the_map; // Private Widget member.

        // This here is a C++11 lambda in a standard loop algorithm, if you didn't recognize the syntax.
        std::for_each(the_map.begin(), the_map.end() [&os](variant_map_t::value_type value)
        {
            os << value.first << '=' << value.second << ' ';
        });
    }
}

我试图删除右手限定符和引用,认为按值传递副本会破坏限定符(根据共享指针可能不那么明亮),并且我已经尝试将声明从命名空间移动到全球范围,希望ADL出于某种原因选择它(从概念上讲,我得到了ADL,但对我来说,它仍然只有一点点黑魔法。)

我不知道还能做什么。除了编译器之外,这个bug的本质是什么,无法找到具有const限定rhs的插入运算符?怎么可能,当它在那里?什么是决议?

1 个答案:

答案 0 :(得分:1)

向命名空间添加typedef没有帮助,std::pairstd::ostream仍然是std命名空间的一部分。因此,编译器将查找<<运算符,而不是命名空间。