获取CRTP继承链中最深的类 [英] Get deepest class in CRTP inheritance chain
问题描述
我想知道如何解决以下问题(C++17):假设有几个模板类,它们以类似 CRTP 的方式相互继承(仅单继承).对于给定的实例化模板基类,找到在继承链中距离它最远的类.
I would like to know how to solve the following problem (C++17): suppose there are several template classes, inherited from each other in CRTP-like fashion (single inheritance only). For a given instantiated template base class, find the class that is furthest from it down the inheritance chain.
我一开始以为这应该很容易,但没能做到.
I first thought that is should be pretty easy, but was not able to accomplish this.
为了简化,假设每个根和每个中间类在其 public
区域中都有 using DerivedT = Derived
.
To simplify, suppose that every root and every intermediate class has using DerivedT = Derived
in its public
area.
示例:
template <class T>
struct GetDeepest {
using Type = ...;
};
template <class T>
struct A {
using DerivedT = T;
};
template <class T>
struct B : public A<B<T>> {
using DerivedT = T;
};
struct C : B<C> {
};
struct D : A<D> {
};
GetDeepest<A<D>>::Type == D;
GetDeepest<B<C>>::Type == C;
GetDeepest<A<B<C>>>::Type == C;
...
我尝试过的第一个实现:
First implementation I've tried:
template <class T>
struct GetDeepest {
template <class Test, class = typename Test::DerivedT>
static std::true_type Helper(const Test&);
static std::false_type Helper(...);
using HelperType = decltype(Helper(std::declval<T>()));
using Type = std::conditional_t<std::is_same_v<std::true_type, HelperType>,
GetDeepest<typename T::DerivedT>::Type,
T>;
};
我尝试过的第二个实现:
Second implementation I've tried:
template <class T>
struct HasNext {
template <class Test, class = typename Test::DerivedT>
static std::true_type Helper(const Test&);
static std::false_type Helper(...);
using HelperType = decltype(Helper(std::declval<T>()));
static const bool value = std::is_same_v<std::true_type, HelperType>;
};
template <class T>
auto GetDeepestHelper(const T& val) {
if constexpr(HasNext<T>::value) {
return GetDeepestHelper(std::declval<typename T::DerivedT>());
} else {
return val;
}
}
template <class T>
struct GetDeepest {
using Type = decltype(GetDeepestLevelHelper(std::declval<T>()));
};
它们都没有编译.
第一个 -- 因为 GetDeepest<T>
在语句 using Type = ...
中的类型不完整,第二个是因为使用 auto
作为返回类型.
First one -- because of incomplete type of GetDeepest<T>
in statement using Type = ...
, second because of recursive call of a function with auto
as a return type.
是否有可能实现具有此类属性的 GetDeepest
类?现在我很好奇,即使这可能不是实现我想要的最佳方式.
Is it even possible to implement GetDeepest<T>
class with such properties? Now I'm very curious, even if it might be not the best way to accomplish what I want.
谢谢!
推荐答案
我不确定我是否完全理解这个问题,所以请随时在评论中问我.
I'm not sure if I fully understand the question so feel free to ask me in comments.
但我认为这应该可行:
#include <type_traits>
template<typename T>
struct GetDeepest
{
using Type = T;
};
template<template<typename> class DT, typename T>
struct GetDeepest<DT<T>>
{
using Type = typename GetDeepest<T>::Type;
};
template <class T>
struct A {
using DerivedT = T;
};
template <class T>
struct B : public A<B<T>> {
using DerivedT = T;
};
struct C : B<C> {
};
struct D : A<D> {
};
int main()
{
static_assert(std::is_same<GetDeepest<A<D>>::Type, D>::value);
static_assert(std::is_same<GetDeepest<B<C>>::Type, C>::value);
static_assert(std::is_same<GetDeepest<A<B<C>>>::Type, C>::value);
}
这篇关于获取CRTP继承链中最深的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!