【问题标题】:How to determine if a type is derived from a template class at compile time?如何在编译时确定类型是否从模板类派生?
【发布时间】:2021-11-22 08:36:57
【问题描述】:

假设我有一些模板类:

template<class T>
class Foo{}

template<class T>
class Bar{}

现在,我想确保(在编译时)Bar 中使用的类型派生自Foo。我已经找到了this 答案,它显示了如何在运行时执行此操作,但我想在编译时检查,可能使用static_assert 或其他东西。
有没有办法做到这一点?

【问题讨论】:

  • 你可以使用一些type-traits
  • @Someprogrammerdude 是的,我调查了一下。 is_base_of 可能有用,但我只知道当 Foo 是普通类而不是模板类时如何使用它。

标签: c++ templates static-assert


【解决方案1】:

现在,我想确保(在编译时)Bar 中使用的类型是从 Foo 派生的。

你可以这样做:

#include<type_traits>
#include<utility>

template<class T>
class Foo{};

template<typename T>
std::true_type test(const Foo<T> &);

std::false_type test(...);

template<class T>
class Bar {
    static_assert(decltype(test(std::declval<T>()))::value, "!");
};

struct S: Foo<int> {};

int main() {
    Bar<S> ok1;
    Bar<Foo<int>> ok2;
    // Bar<int> ko;
}

wandbox上查看。
基本思想是,如果T 派生自Foo 的特化,则无论U 是什么,您都可以将T 类型的临时绑定到const Foo&lt;U&gt; &amp;。因此,您可以声明(无需定义)几个函数,如示例中的函数来测试它,然后在 static_assert 或任何其他常量上下文中使用声明的返回类型。


编辑

正如@Quentin 在 cmets 中所建议的那样,可能值得用指针替换引用以防止转换构造函数和运算符的误报。

【讨论】:

  • 这会准确检查 Foo,OP 想要 Foo 的子类型。
  • @yurikilochek 对。已修复以匹配派生类。
  • 我会用指针替换引用,以防止转换构造函数和运算符的误报。
  • @Quentin 好点。无论如何,我应该能够获取std::declval 返回的地址来做到这一点,我认为没有办法。我错了吗?
  • @skypjack std::declval&lt;T*&gt;() ? ;)
猜你喜欢
  • 2011-08-25
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
相关资源
最近更新 更多