简体   繁体   English

为什么static_cast不使用转换运算符指向const?

[英]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* ,您需要分两步处理:

  1. Pointer<Base>::operator Base const*
  2. downcast. 沮丧。

eg 例如

Base const* pb = static_cast<Base const *>(p);
Derived const *pd = static_cast<Derived const*>(pb);

Live demo . 现场演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么const_cast(或static_cast)不添加const? - Why does a const_cast (or static_cast) not add const? 为什么对volatile int的const引用需要static_cast? - Why does a const reference to volatile int need a static_cast? static_cast,带有显式右值转换运算符 - static_cast with an explicit rvalue conversion operator 具有转换运算符的类上的static_cast - static_cast on class with conversion operator 使用static_cast实现转换运算符 - Conversion operator implemented with static_cast 在Effective C ++ Item 3中,为什么要使用static_cast <const TextBlock&> (* this)而不是static_cast <const TextBlock> (*这个)? - In Effective C++ Item 3,why use static_cast<const TextBlock&>(*this) instead of static_cast<const TextBlock>(*this)? 具有隐式转换运算符的类上的static_cast &lt;&gt;行为,该运算符返回const引用 - static_cast<> behaviour on class with implicit conversion operator that returns a const reference 为什么这种 C 风格的转换不考虑 static_cast 后跟 const_cast? - Why does this C-style cast not consider static_cast followed by const_cast? 为什么我的指针的 static_cast 失败了? - Why is my static_cast of a pointer failing? 对于static_cast和reinterpret_cast,转换运算符int()失败 - Conversion operator int() failed for static_cast and reinterpret_cast
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM