使用 C++20 中派生的“使用”CRTP

sen*_*iwa 2 c++ crtp c++20

我正在尝试了解 CRTP 和 C++20。基本上,我希望拥有可以访问派生类型的typedefs 和 的静态继承using

template <typename Derived>
class inherit
{
public:

    Derived& underlying()
    {
        return static_cast<Derived&>(*this);
    }

    Derived const& underlying() const
    {
        return static_cast<Derived const&>(*this);
    }
};

template <typename Derived>
class tester : public inherit<Derived>
{
public:
    using value_type = typename Derived::value_type;
};

class real : public tester<real>
{
public:
    using value_type = int;
};


int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如有关 SO 的其他一些问题中 所解释的,从 C++14 开始,这是不允许的(我发现的答案参考该标准和 C++11)。我的理解是,C++17 中也没有办法(如果我的编译器是正确的)。

C++20 目前的状况如何?即将推出的标准是否有更好的解决方案?

Nic*_*las 5

不,C++20 中仍然不允许这样做。毫无疑问,在 C++ 中,只要派生类不完整,直到基类模板实例化完成,就仍然不允许这样做。毫无疑问,情况仍然如此,因为您想要的将要求编译器在实例化基类模板之前将派生类编译到某种程度,而这种程度的“前瞻”是不切实际的。并且可能导致无限循环或其他混乱的构造,因为派生类成员声明/定义应该能够访问可访问的基类声明。

考虑一些迭代器需求的简单情况。迭代器必须有一个(暂时value_type忽略整个“ ”业务;我们的目的是使用默认特征),派生类将提供它。iterator_traits我们的辅助迭代器 CRTP 基类将有助于使用派生类value_type声明来生成pointerreference等。但是派生类operator*需要能够返回reference,它是从基类继承的,而基类本身依赖于编译value_type派生类中的声明。那么...哪个首先被编译:基类模板实例化还是派生类?必须是其中之一;两者不能同时存在。

最终的问题是 CRTP 并不是我们真正想要的。我们真正想要的是能够在一个集中位置存储一系列声明/定义,然后根据需要将它们注入到类中。IE:一个实际的 mixin。使用命名派生类的模板类型的继承仅仅是 C++ 语言实现这一目标的最接近的工具。但由于继承和模板实例化从来都不是为了满足这种需求,所以自然会有与之相关的缺点。

因此,您将继续依赖典型的替代方案:使用基于派生类类型模板化的“traits”类。


归档时间:

查看次数:

660 次

最近记录:

7 年,4 月 前