繁体   English   中英

使用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的第二个编译。

我已经试图查看标准(关于static_cast的第5.9节和关于转换的第12.3节),但由于我缺乏经验,我无法找到答案。

我非常感谢任何花时间帮助我解决这个问题的人。

综观[expr.static.cast]n3337(第一标准后工作草案):

2 /类型为“cv1 B ”的左值,其中B是类类型,可以强制转换为类型“引用cv2 D ”,其中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
    // ...
};

外部的代码调用fun1class SomeImpl将获得委托给合适的常量或非const版本self()class enable_crtp和down_casting实施后do_fun1将被调用。 有了一个不错的编译器,所有的间接都应该完全优化掉。

注意: ISomeClassenable_crtp的受保护析构函数使代码对于尝试通过基指针删除SomeImpl*对象的用户安全。

暂无
暂无

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

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