在 C++20 中使用 CRTP 派生 "using"

Using CRTP derived "using" in 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;
}

正如所解释的那样,in some other questions on SO 从 C++14 开始是不允许的(我找到的答案指的是该标准和 C++11)。我的理解是 C++17 也没有办法(如果我的编译器是正确的)。

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

不,在 C++20 中仍然不允许。毫无疑问,只要派生 class 在基本 class 模板完成实例化之前是不完整的,它就不会在 C++ 中被允许。毫无疑问,这将保持现状,因为您想要的是需要编译器在实例化基本 class 模板之前在某种程度上编译派生的 class,而 "look ahead" 的程度只是不实用。并且可能导致无限循环或其他混淆的构造,因为派生的 class 成员 declarations/definitions 应该能够访问可访问的基础 class 声明。

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

最终的问题是 CRTP 并不是我们真正想要的。我们真正想要的是能够在集中位置存储一系列declarations/definitions,然后根据需要将它们注入class。 IE:一个实际的混合。使用命名派生 class 的模板类型的继承只是 C++ 语言必须实现的最接近的工具。但是,由于继承和模板实例化从未打算满足这种需求,因此自然会有与之相关的缺陷。

因此您将不得不继续依赖典型的替代方法:使用在派生的 class 类型上模板化的 "traits" class。