c++ - 获取 CRTP 继承链中最深的类
问题描述
我想知道如何解决以下问题(C++17):假设有几个模板类,以类似 CRTP 的方式相互继承(仅限单一继承)。对于给定的实例化模板基类,找到在继承链中离它最远的类。
我首先认为这应该很容易,但无法做到这一点。
为简化起见,假设每个根和每个中间类都using DerivedT = Derived
在其public
区域内。
例子:
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;
...
我尝试过的第一个实现:
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>;
};
我尝试过的第二个实现:
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>
in 语句的类型不完整using Type = ...
,第二个是因为递归调用auto
作为返回类型的函数。
甚至可以实现GetDeepest<T>
具有这些属性的类吗?现在我很好奇,即使这可能不是实现我想要的最佳方式。
谢谢!
解决方案
我不确定我是否完全理解这个问题,所以请随时在评论中问我。
但我认为这应该有效:
#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);
}
推荐阅读
- php - Podio 在尝试添加在其字段中具有多个标签的项目时抛出 PodioBadRequestError invalid_value int
- excel - 在 VBA 中使用循环删除范围并在每次迭代时更改范围
- python - VsCode 在运行模式和调试模式之间的不同行为
- javascript - 如何使此代码仅显示 600px 及以上?(我不希望它出现在手机或平板电脑上)
- swift - 搜索栏必须显示一个结果,其中每个都必须包含所有搜索的单词,而不管它们的编写顺序如何?
- sql - SQL SERVER 替换空值
- flutter - SingleChildScrollView 显示白色
- javascript - 在创建 API 时修改了来自 nestjs 的 JSON 响应
- linq - LINQ 查询以获取学生课程
- apache-atlas - Apache Atlas:从 Java 客户端连接时出现 Http 503 Service Unavailable 错误