为什么 static_cast 不使用转换运算符指向 const 的指针?
Why does static_cast not use the conversion operator to pointer to const?
从我的包装器 class Pointer<Base>
我只想 return 指向 const 的指针:Base const *
.
将 Pointer<Base>
转换为 Derived const *
时出现编译错误:
error C2440: 'static_cast': 'Pointer' can not be converted to '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; }
它会起作用。
为什么 static_cast
不使用 const 转换运算符?
或者更具体地说,因为
Derived const *pd = static_cast<Derived const *>(static_cast<Base const *>(p));
作品:
为什么 static_cast
可以隐式转换为 Base *
,但不能转换为 Base const *
,即使后者足以满足转换目标类型?
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.
[我强调]
解决方法
因为这看起来像是一个 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(); }
您尝试转换时需要分两步处理 Pointer<Base>*
---(1)---> Base const*
---(2)---> Derived const*
,其中:
Pointer<Base>::operator Base const*
- 沮丧。
例如
Base const* pb = static_cast<Base const *>(p);
Derived const *pd = static_cast<Derived const*>(pb);
只允许转换一次,因此可以转换为Base
,但之后不能转换为Derived
。
所以你必须连续使用两次。无论如何它更安全,因为你声明你知道你正在从 Base
转换为 Derived
。您永远不应该从基 class 到派生 class.
进行隐式转换
从我的包装器 class Pointer<Base>
我只想 return 指向 const 的指针:Base const *
.
将 Pointer<Base>
转换为 Derived const *
时出现编译错误:
error C2440: 'static_cast': 'Pointer' can not be converted to '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; }
它会起作用。
为什么 static_cast
不使用 const 转换运算符?
或者更具体地说,因为
Derived const *pd = static_cast<Derived const *>(static_cast<Base const *>(p));
作品:
为什么 static_cast
可以隐式转换为 Base *
,但不能转换为 Base const *
,即使后者足以满足转换目标类型?
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.
[我强调]
解决方法
因为这看起来像是一个 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(); }
您尝试转换时需要分两步处理 Pointer<Base>*
---(1)---> Base const*
---(2)---> Derived const*
,其中:
Pointer<Base>::operator Base const*
- 沮丧。
例如
Base const* pb = static_cast<Base const *>(p);
Derived const *pd = static_cast<Derived const*>(pb);
只允许转换一次,因此可以转换为Base
,但之后不能转换为Derived
。
所以你必须连续使用两次。无论如何它更安全,因为你声明你知道你正在从 Base
转换为 Derived
。您永远不应该从基 class 到派生 class.