【问题标题】:Overloading the global type conversion operator重载全局类型转换运算符
【发布时间】:2011-01-15 04:00:25
【问题描述】:

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

我有一个 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,甚至对于我的类,我也不想用“用于测试” 转换运算符来污染它们。

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

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

【问题讨论】:

    标签: c++ operators operator-overloading


    【解决方案1】:

    不幸的是,没有全局转换运算符之类的东西。出奇。但是模板是你的朋友。

    有时您不想将强制转换暴露给接口 put 只想为特定实现保持匿名。我通常会在类中添加一个模板 as() 方法,该方法还可以在转换等中进行类型检查,并让您处理想要实现转换的方式(例如动态、共享、引用等)。

    类似这样的:

        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 是一个只有实现知道的匿名类型。虽然这严格来说是非类型转换(我在这里不使用类型检查),但可以用 dynamic_cast 和适当的转换异常来代替。

    实现只是这样做:

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          不,没有这样的事情。转换函数必须是类的成员。如果不是这样,它会引入歧义,从而使重载解析成为编译器特别棘手的问题。

          【讨论】:

          • 但是很多运营商都可以作为全局或会员使用,为什么不是这个呢?例如,如果有一个全局和一个成员运算符
          • 转换函数是特殊的成员函数(如 ctor、dtor、op= 和复制构造函数),因为它们参与转换/对象创建。见 12.3。
          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 2012-01-25
            • 1970-01-01
            • 2013-11-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多