3

一个随机的问题...

我正在寻找的是一种表达转换操作的方法,该操作使用我要转换的类实例的已定义运算符,如果没有为该类型定义的转换运算符,则会生成编译时错误。因此,例如,我正在寻找的是类似的东西:

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

4 回答 4

3

您发布的代码可与Cameau 编译器一起使用(这通常很好地表明它是有效的 C++)。

如您所知,有效的演员表不超过一个用户定义的演员表,所以我想到的一个可能的解决方案是通过在演员表模板中定义一个新类型并有一个静态断言没有可用的演员表来添加另一个用户定义的演员表结果类型的新类型(使用boost is_convertible),但是这不区分强制转换运算符和强制转换构造函数(带有一个参数的 ctor),并允许进行额外的强制转换(例如void*to 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 上,原始版本似乎可以正常工作(就像我的一样)。
  • 在 VS2005 上,原始版本仅在从内置类型(例如,将 int 转换为 int)转换为编译错误后崩溃编译器,这对我来说似乎还不错,而且我的版本似乎在所有情况下都有效。
于 2008-10-21T21:17:15.373 回答
1

使用标记为显式的转换构造函数可以防止编译器允许隐式转换的类型初始化包装类。

于 2008-10-16T19:19:27.610 回答
1

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

#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;
}
于 2008-10-16T21:12:09.957 回答
0

听起来你想要模板专业化,这样的事情会做:

/* 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; }

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

于 2008-10-16T20:51:04.663 回答