c++ - 检查实现了哪些基类
问题描述
我有两个模板类 A 和 B
template <typename T> class A { /* ... */ };
template <typename T> class B { /* ... */ };
现在我想编写一个执行不同操作的函数,具体取决于在传递的参数中实现了哪些基类。
template <typename T>
void foo(const T& object) {
if ( /* T inherits from some A<S1> */ )
std::cout << "object has type A";
if ( /* T inherits from some B<S2> */ )
std::cout << "object has type B";
}
我想我可以将S1
andS2
作为模板参数添加到 foo 但是为每个调用手动指定它们是一个很大的麻烦。理论上,如果T
已知,编译器应该能够检查它是否继承了任何A<S>
.
这可以做到吗?
编辑:
除了 StoryTeller 的解决方案之外,我还使用这段代码来相应地转换我的T
-objects:
template<template<typename...> class TT, class T>
struct specialization_base_of {
template<typename... Args>
static constexpr TT<Args...> checkVal(TT<Args...> const&);
static constexpr void checkVal(...);
template<typename... Args>
static constexpr TT<Args...>& checkRef(TT<Args...> const&);
static constexpr void checkRef(...);
template<typename... Args>
static constexpr TT<Args...> const& checkCref(TT<Args...> const&);
static constexpr void checkCref(...);
template<typename... Args>
static constexpr TT<Args...>* checkPtr(TT<Args...> const&);
static constexpr void checkPtr(...);
using value_type = decltype(checkVal(std::declval<T>()));
using ref_type = decltype(checkRef(std::declval<T>()));
using cref_type = decltype(checkCref(std::declval<T>()));
using ptr_type = decltype(checkPtr(std::declval<T>()));
};
解决方案
依赖重载解析的好老技巧也应该在这里起作用:
template<template<typename...> class TT, class T>
struct is_specialization_base_of {
template<typename... Args>
static constexpr std::true_type check(TT<Args...> const&);
static constexpr std::false_type check(...);
static constexpr bool value = decltype(check(std::declval<T>()))::value;
};
第一个模板参数是模板名称,可以接受任意数量的类型参数。你需要一个,但为什么要限制自己呢?
然后我们定义了两个重载,一个是接受任何假设特化的模板,TT
第二个是作为 C 风格变量参数函数的后备。这是整个机器。如果我们调用check
任何公开派生自 的假设特化的类,TT
则根据重载解析的工作方式选择第一个重载。否则选择后备。
我们的 trait 的值由 的未评估上下文中产生的类型决定,在decltype
那里执行重载决议,但由于它是未评估的上下文,因此无需定义任何内容,只需声明即可。decltype
因此产生结果类型。
struct C1 : A<int> {};
struct C2 : B<int> {};
struct C3 : A<int>, B<char> {};
static_assert(is_specialization_base_of<A, C1>::value);
static_assert(!is_specialization_base_of<B, C1>::value);
static_assert(!is_specialization_base_of<A, C2>::value);
static_assert(is_specialization_base_of<B, C2>::value);
static_assert(is_specialization_base_of<A, C3>::value);
static_assert(is_specialization_base_of<B, C3>::value);
我将把这个特性插入你的模板函数的练习留给你。我只是建议把那些if
' 变成if constexpr
一些额外的好东西。
推荐阅读
- java - 为 BST 支持的符号表创建 Iterable
- r - 奇怪的错误:该表是由 Rstudio 正确生成的,但不是由我创建的站点生成的
- node.js - 在后台实时颤动警报
- lua - Sprite 未在屏幕上绘制 (TIC-80)
- sql - 选择在第二个表上没有关联产品的记录
- php - 使用 PHP 更新 SQLite 数据库
- javascript - 函数在我的 redux 状态可用之前运行,TypeError: Cannot read properties of undefined (reading 'find')
- java - java使用picocli格式化表格输出
- batch-file - 批处理文件以我想要的顺序一次打开多个文件夹
- python - AWS boto3 在 put_subscription_filter 中追加/删除参数