c++ - 在编译时检查未实例化的类模板是否继承自其第一个模板参数

标签 c++ templates c++17 template-templates

小问题

我如何在编译时检查一个(编辑: 未实例化的)类模板是否从 C++17 的第一个模板参数继承?

长问题

我想通过以下方式构造一些东西来确定类模板是否继承自其(第一个)模板参数:

template<template<typename> class TemplateClass>
struct template_parameter_is_base_of
{
    /* Implementation */
};

理想情况下,template_parameter_is_base_of可以这样使用:

template<typename T> struct WithParent : T { /* Implementation */ };
template<typename T> struct WoutParent :   { /* Implementation */ };

static_assert(template_parameter_is_base_of<WithParent>::value); // Ok as expected since WithParent inherits from T
static_assert(template_parameter_is_base_of<WoutParent>::value); // Error as expected since WithParent doesn't inherit from T

我失败的尝试

我尝试实现 template_parameter_is_base_of :

struct Dummy {};

template<template<typename> class TemplateClass>
struct template_parameter_is_base_of
{
    static constexpr bool value = std::is_base_of_v<Dummy, TemplateClass<Dummy>>;
};

...在这种情况下有效:

template<typename T>
struct A : T {
    void work() { /* Irrelevant implementation */ }
};

static_assert(template_parameter_is_base_of<A>::value); // Passes because A inherits from its template parameter. Nice!

... 但是如果类模板有一个带有 override 的方法,它就会失败说明符:

template<typename T>
struct B : T {
    void work() override { /* Irrelevant implementation */ }
};

static_assert(template_parameter_is_base_of<B>::value); // Fails, but I want it to pass because B inherits from its template parameter.

这就是我现在的想法

我想我已经用 Dummy 把自己逼到了一个角落上面使用的方法,因为 TemplateClass<Dummy> 的类模板实例化在 std::is_base_of_v 内如果 TemplateClass 将始终失败包含任何带有 override 的方法说明符。

但是,我认为实现 template_parameter_is_base_of 应该是可能的,因为编译器应该在编译时知道类模板是否继承自其模板参数。也许我错了。

最后的问题

是否可以实现 template_parameter_is_base_of从 C++17 开始?如果是,那该怎么做?

最佳答案

However, I think that implementing template_parameter_is_base_of should be possible because a compiler should know at compile-time whether a template class inherits from its template parameter or not.

模板本质上是一种参数化工具,用于制造某些 C++ 结构:类、函数或变量。模板本身还不是它要制作的东西。类模板不继承任何东西,因为它还不是类。所以问题本身不是一个功能性问题。

与此相结合的是存在显式/部分模板特化这一事实。即使基类模板确实继承了它的第一个模板参数,也不能保证任何事情。你仍然不知道是否有任何特定的 WithParent<T>模板的实例化实际上将使用基本模板。用户可以轻松地专门化 WithParent对于特定类型,甚至对整个类型系列采用部分特化。

你要的不是C++能支持的。如果您试图验证某事或防止某些滥用或其他任何事情,您将不得不以另一种方式进行。

关于c++ - 在编译时检查未实例化的类模板是否继承自其第一个模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58467917/

相关文章:

c++ - 无状态 lambda 作为静态局部变量

c++ - std::move(*this) 是一个好的模式吗?

c++ - 使用 cin 检查空行

c++ - 作为非类型模板参数的函数指针

c++ - 如果类型的大小大于 X,如何实现接受类型并计算引用的类型特征?

c++ - 通过推导强制引用模板类型

C++类定义编译问题

c++ - 超出范围的模板参数的预期行为?

c++ - 有没有办法让这个 C++14 递归模板在 C++17 中更短?

c++ - 你如何对每个元素执行转换并将结果附加到 C++ 中?