7

在我在这里提出的问题之后,我提出了这个问题。

要点很简单。假设您有两个此类:

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 节),但由于缺乏经验,我无法找出答案。

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

4

2 回答 2

3

查看n3337中的[expr.static.cast] 标准之后的第一个工作草案):

2/类型“cv1 B”的左值,其中B是类类型,可以转换为类型“对 cv2 的引用” D,如果从“指向”的有效标准转换为“指向“的指针存在 [...]DBDB

4/否则,如果声明格式正确,则表达式e可以T使用static_cast形式的 a 显式转换为类型,对于某些发明的临时变量[..]static_cast<T>(e)T t(e);t

因此,我认为 gcc 的行为是正确的,即表达式:

static_cast<Derived const&>(*this)

不应该递归调用operator Derived const& () const

我从else关键字的存在推断出这一点,这意味着规则的排序。规则2/应该在规则之前被尝试4/

于 2012-03-22T10:28:34.753 回答
0

不推荐使用隐式转换运算符。在 C++11 中,您不仅可以将关键字添加explicit到单参数构造函数,还可以添加到转换运算符。对于 C++03 代码,您可以使用显式命名的转换函数,例如self()down_cast()

此外,您似乎正在使用BaseCRTP 类,即启用静态多态性。这意味着您必须在编译时Derived知道您正在调用哪个特定类。const Base&因此,除了实现 CRTP 接口外,您不必在任何公共代码中使用引用。

在我的项目中,我有一个类模板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 或非 const 版本,self()并且class enable_crtp在 down_casting 之后do_fun1将调用实现。使用一个体面的编译器,所有的间接都应该被完全优化掉。

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

于 2012-04-18T14:47:45.107 回答