[英]Conversion operator implemented with static_cast
我在这里提出的问题之后问这个问题。
这一点非常简单。 假设你有两类这样的类:
template < class Derived >
class Base {
...
operator const Derived&() const {
return static_cast< const Derived& >(*this);
}
...
};
class Specialization : public Base<Specialization> {
...
};
然后假设您有类似这样的类型转换:
template < class T >
functionCall( const Base<T>& param) {
const T & val(param);
...
}
问题是: 这种转换的标准符合行为应该是什么?
它应该与const T & val(static_cast<const T &> (param) )
还是应该递归迭代直到堆栈溢出? 请注意,我获得了使用GNU g++
编译的第一个行为,以及使用Intel icpc
的第二个编译。
我已经试图查看标准(关于static_cast的第5.9节和关于转换的第12.3节),但由于我缺乏经验,我无法找到答案。
我非常感谢任何花时间帮助我解决这个问题的人。
综观[expr.static.cast]在n3337(第一标准后工作草案):
2 /类型为“cv1
B
”的左值,其中B
是类类型,可以强制转换为类型“引用cv2D
”,其中D
是从B
派生的类(第10条),如果有效的标准转换来自“指向D
“指向B
”的指针存在[...]4 /否则,表达
e
可以显式转换到类型T
使用static_cast
形式static_cast<T>(e)
,如果声明T t(e);
形成良好,对于一些发明的临时变量t
[..]
因此,我会解释gcc的行为是正确的,即表达式:
static_cast<Derived const&>(*this)
不应该调用递归operator Derived const& () const
。
我推断这从否则关键字的存在,这意味着的规则的排序。 规则2/
应规则之前受审4/
。
不建议使用隐式转换运算符。 在C ++ 11中,您不仅可以将关键字explicit
添加到单个参数构造函数,还可以添加到转换运算符。 对于C ++ 03代码,您可以使用显式命名的转换函数,例如self()
或down_cast()
。
此外,您似乎使用Base
类进行CRTP,即启用静态多态。 这意味着你必须在编译时知道你正在调用哪个特定的Derived
类。 因此,除了实现CRTP接口之外,您不必在任何公共代码中使用const Base&
引用。
在我的项目中,我有一个类模板enable_crtp
:
#include <type_traits>
#include <boost/static_assert.hpp>
template
<
typename Derived
>
class enable_crtp
{
public:
const Derived& self() const
{
return down_cast(*this);
}
Derived& self()
{
return down_cast(*this);
}
protected:
// disable deletion of Derived* through Base*
// enable deletion of Base* through Derived*
~enable_crtp()
{
// no-op
}
private:
// typedefs
typedef enable_crtp Base;
// cast a Base& to a Derived& (i.e. "down" the class hierarchy)
const Derived& down_cast(const Base& other) const
{
BOOST_STATIC_ASSERT((std::is_base_of<Base, Derived>::value));
return static_cast<const Derived&>(other);
}
// cast a Base& to a Derived& (i.e. "down" the class hierarchy)
Derived& down_cast(Base& other)
{
// write the non-const version in terms of the const version
// Effective C++ 3rd ed., Item 3 (p. 24-25)
return const_cast<Derived&>(down_cast(static_cast<const Base&>(other)));
}
};
这个类是由任何CRTP基类ISomeClass私下派生的,如下所示:
template<typename Impl>
class ISomeClass
:
private enable_crtp<Impl>
{
public:
// interface to be implemented by derived class Impl
void fun1() const
{
self().do_fun1();
}
void fun2()
{
self().do_fun2()
}
protected:
~ISomeClass()
{}
};
各种派生类可以按照自己的特定方式实现此接口,如下所示:
class SomeImpl
:
public ISomeClass<SomeImpl>
{
public:
// structors etc.
private:
// implementation of interface ISomeClass
friend class ISomeClass<SomeImpl>;
void do_fun1() const
{
// whatever
}
void do_fun2()
{
// whatever
}
// data representation
// ...
};
外部的代码调用fun1
的class SomeImpl
将获得委托给合适的常量或非const版本self()
在class enable_crtp
和down_casting实施后do_fun1
将被调用。 有了一个不错的编译器,所有的间接都应该完全优化掉。
注意: ISomeClass
和enable_crtp
的受保护析构函数使代码对于尝试通过基指针删除SomeImpl*
对象的用户安全。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.