重载全局类型转换运算符

时间:2010-02-10 07:54:39

标签: c++ operators operator-overloading

为了测试和显示我的库的某些功能的结果,我正在创建一组方便的功能。

我有一个execute函数,如下所示:

template <typename R, typename I>
std::string execute( const std::string& func_name, R(*func_ptr)( const I& ), const I& func_input );

它调用该函数,并以格式化的字符串显示结果和参数,我可以将其发送到std::cout

问题是我的一些函数没有返回 convertible-to-string 结果。我以为我可以简单地用例如:

重载全局::operator std::string
template <typename T>
operator std::string( const std::vector<T>& v );
但是GCC抱怨说:

error: 'operator std::string(const std::vector<T, std::allocator<_CharT> >&)' must be a nonstatic member function

嗯,问题当然是我无法将成员运算符添加到std::vector,甚至对于我的类,我也不想用“进行测试”转换来污染它们运算符。

我想我可以添加一个间接层并使用函数而不是转换运算符,但这不是更美观的解决方案。我也可以为::operator <<重载std::ostream并使用std::ostringstream,但这也不是最干净的解决方案。

我想知道全局转换运算符是否真的不可重载,如果是,为什么。

5 个答案:

答案 0 :(得分:12)

转换运算符(强制转换运算符)必须是生成转换类型的可转换类的成员。作为赋值运算符,它们必须是成员函数,正如编译器告诉你的那样。

根据您希望将多少工作量放入调试部分,您可以尝试使用元编程将执行方法转发到不同的实际实现,为打印内容的容器提供特定的实现。

为什么不为您的类型提供operator<<?我认为这实际上是惯用的解决方案。与使用转换为字符串以生成可打印结果的方法的其他语言不同,在C ++中,惯用方法是提供operator<<,然后使用stringstreams(或boost::lexical_cast或类似的解决方案)进行转换基于operator<<实现的字符串。有一个简单的实用工具类here可以从覆盖string的元素创建operator<<,如果您想将其用作起点。

答案 1 :(得分:5)

  

我想知道全局转换运算符是否真的不可重载,如果是,为什么。

不,没有这样的事情。转换函数必须是类的成员。如果不是这样,那么通过引入歧义会使重载决策成为编译器特别棘手的问题。

答案 2 :(得分:1)

没有用户定义的全局转换运算符。您必须控制目标类型(在这种情况下,非显式的一个参数构造函数是转换运算符)或源类型(在这种情况下,您必须重载成员运算符target())。

答案 3 :(得分:0)

转换函数必须是成员函数。该函数可能未指定返回类型,参数列表必须为空。它们应该谨慎使用,并且应该有一种从一种类型到另一种类型的明确转换路径。否则会导致意外结果和神秘错误。

答案 4 :(得分:0)

不幸的是,没有全球演员运营商这样的东西。出奇。但模板是你的朋友。

有时您不希望将转换暴露给接口,而是希望仅为特定实现保持匿名。我通常在类中添加一个模板as()方法,它也可以在强制转换等中进行类型检查,并让你处理你想要实现强制转换的方式(例如dynamic,shared,ref等)。

这样的事情:

    template< class EvtT >const EvtT& as() const throw( std::exception )
    {
        const EvtT* userData = static_cast<const EvtT*>( m_UserData );
        ASSERT( userData, "Fatal error! No platform specific user data in input event!" );
        return *userData;
    }

m_UserData是一种匿名类型,只有实现知道。虽然这是严格的非类型转换(我不在这里使用类型cecks),但可以用dynamic_cast和正确的转换异常替换它。

实施只是这样做:

    unsigned char GetRawKey( const InputEvent& ie )
    {
        const UserEvent& ue = ie.as<const UserEvent>();
        ...