任何方式只与类运算符? [英] Any way to cast with class operator only?

查看:189
本文介绍了任何方式只与类运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个随机问题的类型...



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

  template< typename RESULT_TYPE,typename INPUT_TYPE> 
RESULT_TYPE operator_cast(const INPUT_TYPE& tValue)
{
return tValue.operator RESULT_TYPE();
}

//应该工作...
CString sString;
LPCTSTR pcszString = operator_cast< LPCTSTR>(sString);

//应该失败...
int iValue = 42;
DWORD dwValue = operator_cast< DWORD>(iValue);

有趣的附注:上述代码导致VS2005 C ++编译器崩溃, VS2008 C ++编译器由于我猜测是一个编译器错误,但是希望可以证明这个想法。



任何人都知道任何方式来实现这种效果? >

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



诚然,这是一个罕见的情况,但令人讨厌的是,我不能准确表达我想要的编译器在一个封装函数中做...因此这里的问题。

解决方案

您发布的代码与 Cameau编译器(这通常是一个很好的迹象,它是有效的C ++)。



由于你知道一个有效的转换由不多于一个用户定义的转换组成,所以一个可能的解决方案是通过定义一个新的类型来添加另一个用户定义的转换在投放模板中并拥有 static assert 无法投放可从新类型到结果类型(使用 boost is_convertible ),但是这不区分cast操作符和转换构造函数(具有一个参数的ctor),并且不会进行额外的转换(例如 void * bool )。我不知道如何区分铸造操作符和铸造构造函数是正确的事情,但这是问题的状态。



经过几天的时间仔细考虑它,它打我,你可以简单地获取转换操作符的地址。这说起来容易些,因为C ++对成员语法的毛茸茸的指针(它使我比预期更长的时间来获得正确的)。

 模板<类型名Res,类型名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)转换时崩溃编译器提供了一个编译错误,似乎不太好我和我的版本似乎在所有情况下都有效。


Kind of a random question...

What I'm looking for is a way to express a cast operation which uses a defined operator of the class instance I'm casting from, and generates a compile-time error if there is not a defined cast operator for the type. So, for example, what I'm looking for is something like:

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 );

Interesting side-note: The above code crashes the VS2005 C++ compiler, and doesn't compile correctly in the VS2008 C++ compiler due to what I'm guessing is a compiler bug, but hopefully demonstrates the idea.

Anybody know of any way to achieve this effect?

Edit: More rationale, to explain why you might use this. Say you have a wrapper class which is supposed to encapsulate or abstract a type, and you're casting it to the encapsulated type. You could use static_cast<>, but that might work when you wanted it to fail (ie: the compiler chooses an operator which is allowed to convert to the type you asked for, when you wanted a failure because that operator is not present).

Admittedly it's an uncommon case, but it's annoying that I can't express exactly what I want the compiler to do in an encapsulated function... hence the question here.

解决方案

The code you posted works with the Cameau compiler (which is usually a good indication that it's valid C++).

As you know a valid cast consists of no more than one user defined cast, so a possible solution I was thinking of was adding another user defined cast by defining a new type in the cast template and having a static assert that no cast is available from the new type to the result type (using boost is_convertible), however this doesn't distinguish between cast operators and cast constructors (ctor with one argument) and alows additional casts to take place (e.g. void* to bool). I'm not sure if making a distinction between cast operators and cast constructors is the the correct thing to do but that's what the question states.

After a couple of days mulling this over it hit me, you can simply take the address of the cast operator. This is slightly easier said than done due to C++'s hairy pointer to member syntax (it took me way longer than expected to get it right). I don't know if this works on VS2008, I only checked it on 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)();
}

Edit: I got a chance to test it on VS2005 and VS2008. My findings differ from the original poster's.

  • On VS2008 the original version seems to work fine (as does mine).
  • On VS2005 the original version only crashes the compiler when casting from a built in type (e.g. casting int to int) after providing a compilation error which doesn't seem so bad too me and my version seems to works in all cases.

这篇关于任何方式只与类运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆