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

有没有只使用类运算符进行强制转换的方法?

  •  3
  • Nick  · 技术社区  · 17 年前

    template< typename RESULT_TYPE, typename INPUT_TYPE >
    RESULT_TYPE operator_cast( const INPUT_TYPE& tValue )
    {
        return tValue.operator RESULT_TYPE();
    }
    
    // Should work...
    CString sString;
    LPCTSTR pcszString = operator_cast< LPCTSTR >( sString );
    
    // Should fail...
    int iValue = 42;
    DWORD dwValue = operator_cast< DWORD >( iValue );
    

    有趣的侧记:上面的代码崩溃了VS2005 C++编译器,并且在VS2008 C++编译器中编译不正确,因为我猜的是编译器错误,但是希望演示这个想法。

    有人知道达到这种效果的方法吗?

    编辑:更多的理由,来解释为什么你可能会使用这个。假设您有一个包装器类,它应该封装或抽象一个类型,并且您正在将它转换为封装的类型。您可以使用static_cast<>,但是,当您希望它失败时,这可能会起作用(即:编译器选择一个允许转换为您要求的类型的运算符,当您希望失败时,因为该运算符不存在)。

    4 回复  |  直到 17 年前
        1
  •  3
  •   Motti    17 年前

    您发布的代码与 Cameau compiler

    正如您所知,一个有效的强制转换只包含一个用户定义的强制转换,因此我考虑的一个可能的解决方案是通过在强制转换模板中定义一个新类型并使用 static assert 没有从新类型到结果类型的强制转换(使用 boost is_convertible void* bool ).我不确定区分强制转换运算符和强制转换构造函数是否是正确的做法 对的 但问题是这样的。

    经过几天的深思熟虑后,我突然想到,你可以简单地记下演员接线员的地址。说起来容易做起来难一点,因为C++有一个指向成员语法的毛茸茸的指针(我花了比预期更长的时间才把它弄好)。我不知道这在VS2008上是否有效,我只是在Cameau上检查过。

    template< typename Res, typename T>
    Res operator_cast( const T& t )
    {
        typedef Res (T::*cast_op_t)() const;
        cast_op_t cast_op = &T::operator Res;
        return (t.*cast_op)();
    }
    

    编辑: 我有机会在VS2005和VS2008上测试它。我的发现与原始海报不同。

    • 在VS2008上,原始版本似乎工作正常(就像我的一样)。
        2
  •  1
  •   Community Mohan Dere    9 年前

    使用标记为 explicit 是如何防止编译器允许隐式转换的类型初始化包装器类的。

        3
  •  1
  •   user23167    17 年前

    由于与模板相关的编译器错误消息通常很难解释,如果您不介意指定每个转换,那么也可以通过提供默认模板定义,让编译器在失败情况下发出更具指导性的消息。这使用了编译器只会尝试在实际调用的模板中编译代码这一事实。

    #include <string>
    
    // Class to trigger compiler warning   
    class NO_OPERATOR_CONVERSION_AVAILABLE
    {
    private:
       NO_OPERATOR_CONVERSION_AVAILABLE(){};
    };
    
    // Default template definition to cause compiler error
    template<typename T1, typename T2> T1 operator_cast(const T2&)
    {
       NO_OPERATOR_CONVERSION_AVAILABLE a;
       return T1();
    }
    
    // Template specialisation
    template<> std::string operator_cast(const std::string &x)
    {
       return x;
    }
    
        4
  •  0
  •   Evan Teran    17 年前

    听起来您需要模板专门化,类似这样做:

    /* general template */
    template<typename T1, typename T2> T1 operator_cast(const T2 &x);
    
    /* do this for each valid cast */
    template<> LPCTSTR operator_cast(const CString &x) { return (LPCTSTR)x; }
    

    编辑:如另一篇文章所述,如果执行了不支持的强制转换,您可以在通用版本中添加一些内容,以提供更有用的错误消息。