[英]Why does static_cast not use the conversion operator to pointer to const?
From my wrapper class Pointer<Base>
I'd like to only return pointers to const: Base const *
. 从我的包装类
Pointer<Base>
我只想返回指向const的指针: Base const *
。
When casting Pointer<Base>
to Derived const *
I get a compile error: 将
Pointer<Base>
为Derived const *
出现编译错误:
error C2440: 'static_cast': 'Pointer' can not be converted to 'const Derived *'
错误C2440:'static_cast':'指针'无法转换为'const Derived *'
(translated from german VS2012) (翻译自德语VS2012)
struct Base { };
struct Derived : public Base { };
template <typename T>
class Pointer {
public:
Pointer(T *t = nullptr) : p(t) { }
//operator T*() { return p; }
operator T const *() const { return p; }
template <typename U>
inline U staticCast() const { return static_cast<U>(d); }
private:
T *p;
};
int main(int argc, char *argv[]) {
Derived d;
Pointer<Base> p(&d);
Derived const *pd = static_cast<Derived const *>(p);
}
If I enable the conversion operator T*() { return p; }
如果我启用转换
operator T*() { return p; }
operator T*() { return p; }
it works. operator T*() { return p; }
它的工作原理。
Why doesn't static_cast
use the const conversion operator? 为什么
static_cast
不使用const转换运算符?
Or more specifically, since 或者更具体地说,因为
Derived const *pd = static_cast<Derived const *>(static_cast<Base const *>(p));
works: 作品:
Why can static_cast
implicitly cast to Base *
, but not to Base const *
, even though the latter is sufficient for the cast target type? 为什么
static_cast
可以隐式地转换为Base *
,但不能转换为Base const *
,即使后者足够用于转换目标类型?
The standard says : 标准说 :
If there is an implicit conversion sequence from expression to new_type, or if overload resolution for a direct initialization of an object or reference of type new_type from expression would find at least one viable function, then static_cast(expression) returns the imaginary variable Temp initialized as if by new_type Temp(expression);, which may involve implicit conversions , a call to the constructor of new_type or a call to a user-defined conversion operator .
如果存在从表达式到new_type的隐式转换序列,或者如果从表达式直接初始化对象或类型new_type的引用的重载解析将找到至少一个可行函数,则static_cast(expression)返回初始化为的虚构变量Temp if by new_type Temp(expression);,可能涉及隐式转换 ,调用new_type的构造函数或调用用户定义的转换运算符 。
[Emphasis by me] [由我强调]
Workaround 解决方法
Since this seems like a VisualStudio bug, I will use a workaround instead by means of a templated member function staticCast()
(see sample code above), to be used like this: 由于这似乎是一个VisualStudio错误,我将使用一个变通方法,通过模板化成员函数
staticCast()
(参见上面的示例代码),使用如下:
Derived const *pd = p.staticCast<Derived const *>();
To allow only casts to U const *
, use SFINAE: 要仅允许转换为
U const *
,请使用SFINAE:
template <typename U>
struct is_pointer_to_const
{
static const bool value = std::is_pointer<U>::value
&& std::is_const<typename std::remove_pointer<U>::type >::value;
};
template <typename U>
inline U staticCast(typename std::enable_if<is_pointer_to_const<U>::value >::type* = 0) const
{ return static_cast<U>(d); }
template <typename U>
inline U staticCast(typename std::enable_if<!is_pointer_to_const<U>::value >::type* = 0) const
{ static_assert(false, "Type is not a pointer to const"); return U(); }
There is only one conversion allowed, so you can convert to Base
, but it cannot be converted afterwards to Derived
. 只允许一次转换,因此您可以转换为
Base
,但之后无法将其转换为Derived
。
So you have to use two consecutive casts. 所以你必须使用两个连续的演员表。 It's safer anyway because you state that you know that you are converting from a
Base
to a Derived
. 无论如何它更安全,因为你声明你知道你正在从
Base
转换为Derived
。 You should never have an implicit conversion from a base class to a derived class. 您永远不应该从基类到派生类的隐式转换。
You need to process in two steps as you're trying to convert Pointer<Base>*
---(1)---> Base const*
---(2)---> Derived const*
, with: 当您尝试转换
Pointer<Base>*
---(1)---> Base const*
---(2)---> Derived const*
,您需要分两步处理:
Pointer<Base>::operator Base const*
eg 例如
Base const* pb = static_cast<Base const *>(p);
Derived const *pd = static_cast<Derived const*>(pb);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.