代码之家  ›  专栏  ›  技术社区  ›  NewbiZ

重载全局类型转换运算符

  •  10
  • NewbiZ  · 技术社区  · 15 年前

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

    我有一个 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 .

    问题是我的一些函数没有返回 可转换为字符串 结果。我以为我可以让全球经济超负荷运转 ::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 回复  |  直到 12 年前
        1
  •  11
  •   Community CDub    8 年前

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

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

    为什么不提供 operator<< 适合你的类型?我认为这实际上是惯用的解决方案。与使用转换为字符串以生成可打印结果的方法不同的是,在C++中,习惯用法是提供 操作员<< 然后使用 stringstreams (或) boost::lexical_cast 或类似的解决方案)转换为基于 操作员<< 实施。有一个简单的实用程序类 here 创建一个 string 从重写的元素 操作员<< 如果你想用它作为起点。

        2
  •  4
  •   dirkgently    15 年前

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

    不,没有这样的事。转换函数必须是类的成员。如果不是这样,它将通过引入歧义使重载解决成为编译器特别恼人的问题。

        3
  •  1
  •   AProgrammer    15 年前

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

        4
  •  0
  •   Zoli    15 年前

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

        5
  •  0
  •   jschober    12 年前

    不幸的是,没有一个全球性的演员阵容。令人惊讶。但是模板是你的朋友。

    有时,您不希望将强制转换公开到接口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是一个只有实现知道的匿名类型。虽然这是一个严格的非类型转换(这里我不使用CECK类型),但可以用动态转换和适当的转换异常来替换它。

    实现只需执行以下操作:

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