在 C++20 中使用 CRTP 派生 "using"
Using CRTP derived "using" in C++20
我正在努力研究 CRTP 和 C++20。基本上,我想要静态继承,可以访问派生类型的 typedef
s 和 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
声明来生成 pointer
、reference
等。但是派生的class的operator*
需要能够returnreference
,这是继承自基class,它本身依赖于编译value_type
派生中的声明 class。那么...哪个先编译:基础 class 模板实例化还是派生的 class?它必须是其中之一;两者不能同时存在。
最终的问题是 CRTP 并不是我们真正想要的。我们真正想要的是能够在集中位置存储一系列declarations/definitions,然后根据需要将它们注入class。 IE:一个实际的混合。使用命名派生 class 的模板类型的继承只是 C++ 语言必须实现的最接近的工具。但是,由于继承和模板实例化从未打算满足这种需求,因此自然会有与之相关的缺陷。
因此您将不得不继续依赖典型的替代方法:使用在派生的 class 类型上模板化的 "traits" class。
我正在努力研究 CRTP 和 C++20。基本上,我想要静态继承,可以访问派生类型的 typedef
s 和 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
声明来生成 pointer
、reference
等。但是派生的class的operator*
需要能够returnreference
,这是继承自基class,它本身依赖于编译value_type
派生中的声明 class。那么...哪个先编译:基础 class 模板实例化还是派生的 class?它必须是其中之一;两者不能同时存在。
最终的问题是 CRTP 并不是我们真正想要的。我们真正想要的是能够在集中位置存储一系列declarations/definitions,然后根据需要将它们注入class。 IE:一个实际的混合。使用命名派生 class 的模板类型的继承只是 C++ 语言必须实现的最接近的工具。但是,由于继承和模板实例化从未打算满足这种需求,因此自然会有与之相关的缺陷。
因此您将不得不继续依赖典型的替代方法:使用在派生的 class 类型上模板化的 "traits" class。