使用static_cast实现的转换运算符
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
编译的第二个行为。
我已经试着看一下这个标准(第5.9节关于static_cast,第12.3节关于转换),但由于缺乏经验,我无法找到答案。
我首先非常感谢任何花时间帮助我的人。
查看n3337中的[expr.static.cast](标准后的第一个工作草案):
2/如果存在从"指向
D
的指针"到"指向B
的指针"的有效标准转换,则类型为"cv1B
"的左值(其中B
是类类型)可以强制转换为类型"指向cv2D
的引用",其中D
是从B
派生的类(第10条)[…]4/否则,对于某些发明的临时变量
t
[..],如果声明T t(e);
格式良好,则表达式e
可以使用形式为static_cast<T>(e)
的static_cast
显式转换为类型T
因此,我认为gcc的行为是正确的,即表达式:
static_cast<Derived const&>(*this)
不应递归调用CCD_ 17。
我从Others关键字的存在推断出这一点,该关键字意味着规则的排序。规则2/
应该在规则4/
之前进行尝试。
不建议使用隐式转换运算符。在C++11中,您不仅可以将关键字explicit
添加到单参数构造函数中,还可以添加到转换运算符中。对于C++03代码,可以使用显式命名的转换函数,如self()
或down_cast()
。
此外,您似乎正在为CRTP使用Base
类,即启用静态多态性。这意味着您必须在编译时知道要调用哪个特定的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
// ...
};
调用class SomeImpl
的fun1
的外部代码将被委托给class enable_crtp
中的self()
的适当常量或非常量版本,并且在down_cast之后将调用实现do_fun1
。有了一个不错的编译器,所有的间接寻址都应该完全优化掉。
注意:受保护的ISomeClass
和enable_crtp
的析构函数使代码对试图通过基指针删除SomeImpl*
对象的用户是安全的。
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 构造函数和转换运算符之间的重载解析
- 分配给转换运算符失败-C++
- 转换运算符不适用于sleep_until
- 继承模板化转换运算符
- 模板转换运算符在 clang 6 和 clang 7 之间的区别
- 如何在模板化转换运算符中消除此构造的歧义?
- 为什么选择转换运算符的重载?
- 如何避免强制转换运算符 () 和访问运算符 [] 冲突?
- 如果可能的话,C++总是更喜欢右值引用转换运算符而不是常量左值引用吗?
- 了解转换运算符的选择C++
- 多个隐式转换运算符
- 这个typedef和转换运算符语法是什么意思
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 类模板忽略了用户定义的转换运算符(非模板不忽略)
- 为什么在std::for_each()返回时调用转换运算符
- 为什么 std::optional 的强制转换运算符被忽略了
- 使用用户定义的转换运算符推导函数模板参数
- 模板转换运算符的分辨率不明确
- 统一初始化是隐式发生的,即使 int 强制转换运算符是使用 explicit 关键字声明的.原因是什么?