C++ 使用静态_cast实现的转换运算符

C++ 使用静态_cast实现的转换运算符,c++,standards,crtp,static-cast,conversion-operator,C++,Standards,Crtp,Static Cast,Conversion Operator,我在提出这个问题之后提出了这个问题 问题很简单。假设您有两个此类的类: template < class Derived > class Base { ... operator const Derived&() const { return static_cast< const Derived& >(*this); } ... }; class Specialization : public Base<Specialization>

我在提出这个问题之后提出了这个问题

问题很简单。假设您有两个此类的类:

template < class Derived >
class Base {
...
operator const Derived&() const {
    return static_cast< const Derived& >(*this);
  }
...
};

class Specialization : public Base<Specialization> {
...
};
模板
阶级基础{
...
运算符常量派生(()常量){
返回静态_cast(*this);
}
...
};
阶级专业化:公共基础{
...
};
然后假设您有一个类型转换,如下所示:

template < class T >
functionCall( const Base<T>& param) {
  const T & val(param);
  ...
}
模板
函数调用(常量基和参数){
常数T&val(参数);
...
}
问题是:这种转换的标准一致性行为应该是什么?

它应该与
const T&val(static_cast(param))
相同,还是应该递归迭代直到堆栈溢出?请注意,我使用GNU
g++
进行了第一次行为编译,使用Intel
icpc
进行了第二次编译

我已经试着看了看标准(第5.9节关于静态转换,第12.3节关于转换),但由于缺乏经验,我无法找到答案


在此,我首先非常感谢任何花时间帮助我的人。

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

2/类型为“cv1
B
”的左值,“其中
B
是类类型,可以转换为类型”引用cv2
D
,“其中
D
是从
B
派生的类(第10条),前提是存在从“指向
D
”到“指向
B
”的有效标准转换[……]

4/否则,表达式
e
可以使用
static\u cast(e)
形式的
static\u cast(e)
显式转换为类型
T
,如果声明
T(e);
格式良好,对于一些发明的临时变量
T
[…]

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

static_cast<Derived const&>(*this)
static_cast(*this)
不应递归调用
运算符派生的常量&()常量


我从Otherwise关键字的存在中推断出这一点,它意味着规则的顺序。在规则
4/
之前,应该尝试规则
2/
,不建议使用隐式转换运算符。在C++11中,您不仅可以将关键字
explicit
添加到单参数构造函数,还可以添加到转换运算符。对于C++03代码,可以使用显式命名的转换函数,例如
self()
down\u cast()

此外,您似乎正在为CRTP使用
Base
类,即启用静态多态性。这意味着您必须在编译时知道调用哪个特定的
派生的
类。因此,除了实现nt是一个CRTP接口

在我的项目中,我有一个类模板
enable\u 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)));
        }
};
#包括
#包括
模板
<
派生的类型名
>
类启用\u crtp
{
公众:
常量派生&自()常量
{
返回下掷(*此);
}
派生自()
{
返回下掷(*此);
}
受保护的:
//禁用通过基*
//允许通过派生文件删除基**
~enable_crtp()
{
//无操作
}
私人:
//typedefs
typedef启用\u crtp基础;
//将一个基类强制转换为派生类(即“向下”类层次结构)
常量派生和向下转换(常量基本和其他)常量
{
BOOST_STATIC_ASSERT((std::is_base_of::value));
返回静态_-cast(其他);
}
//将一个基类强制转换为派生类(即“向下”类层次结构)
派生和向下浇铸(基础和其他)
{
//根据常量版本编写非常量版本
//有效C++第三版,第3项(第24至25页)
返回常量投射(向下投射(静态投射(其他));
}
};
此类由任何CRTP基类私有派生,如下所示:

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
    // ...
};
模板
类等距类
:
专用启用\u crtp
{
公众:
//由派生类Impl实现的接口
void fun1()常量
{
self().do_fun1();
}
void fun2()
{
self().do_fun2()
}
受保护的:
~class()
{}  
};
各种派生类可以用自己的特定方式实现此接口,如下所示:

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
:
公共课
{
公众:
//结构等。
私人:
//接口类的实现
朋友班;
void do_fun1()常量
{
//随便
}
void do_fun2()
{
//随便
}
//数据表示
// ...
};
类SomeImpl
的外部代码调用
fun1
将被委托给
self()的相应常量或非常量版本
类enable\u crtp
中,在向下转换后,将调用实现
do\u fun1
。有了一个像样的编译器,所有间接操作都应该完全优化掉


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

相关部分将是关于重载解析的部分。如果你能满足我的好奇心,为什么你要在
base?@Tony Delroy:1)没有显式调用类方法那么冗长。2)我在网络上发现了这种代码,当时我正试图获得一些关于CRTPs的知识,请参见示例3)在发现这种奇怪的行为后,我真的很好奇应该使用哪种方法