繁体   English   中英

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

[英]Why does static_cast not use the conversion operator to pointer to const?

从我的包装类Pointer<Base>我只想返回指向const的指针: Base const *
Pointer<Base>Derived const *出现编译错误:

错误C2440:'static_cast':'指针'无法转换为'const Derived *'

(翻译自德语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);
}

如果我启用转换operator T*() { return p; } operator T*() { return p; }它的工作原理。

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

或者更具体地说,因为

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

作品:

为什么static_cast可以隐式地转换为Base * ,但不能转换为Base const * ,即使后者足够用于转换目标类型?


标准说

如果存在从表达式到new_type的隐式转换序列,或者如果从表达式直接初始化对象或类型new_type的引用的重载解析将找到至少一个可行函数,则static_cast(expression)返回初始化为的虚构变量Temp if by new_type Temp(expression);,可能涉及隐式转换 ,调用new_type的构造函数或调用用户定义的转换运算符

[由我强调]


解决方法

由于这似乎是一个VisualStudio错误,我将使用一个变通方法,通过模板化成员函数staticCast() (参见上面的示例代码),使用如下:

Derived const *pd = p.staticCast<Derived const *>();

要仅允许转换为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(); }

只允许一次转换,因此您可以转换为Base ,但之后无法将其转换为Derived

所以你必须使用两个连续的演员表。 无论如何它更安全,因为你声明你知道你正在从Base转换为Derived 您永远不应该从基类到派生类的隐式转换。

当您尝试转换Pointer<Base>* ---(1)---> Base const* ---(2)---> Derived const* ,您需要分两步处理:

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

例如

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

现场演示

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM