静态断言基类模板的继承

statically assert inheritance of base class template

提问人: 提问时间:8/25/2023 更新时间:8/25/2023 访问量:63

问:

如何在下面的代码中实现编译器将从混音器中的断言返回预期的编译错误消息(参见选项 B)?

#include<iostream>
#include<type_traits>

template<typename _T>
struct Base{
    using T=_T;
};

template<typename _T>
struct Derived: Base<_T>{};

template<typename _T>
struct Underived{};

template<typename Q, typename P>
struct Tumbler{};

// CODE OPTION A
template<typename TDerived>
using Mixer = Tumbler<TDerived,typename TDerived::T>;

// CODE OPTION B
template<typename TDerived>
struct Mixer: Tumbler<TDerived,typename TDerived::T>{
    static_assert(std::is_convertible<TDerived*, Base<typename TDerived::T>*>::value, "TDerived must be derived of Base");
};

int main(){
    Mixer<  Derived<float>> mixer_intend;
    Mixer<Underived<float>> mixer_misuse; // spits error: "T undefined". I want error "is not derived of base"
    std::cout << "passed\n";
}

眼前的问题是,如果不了解 T 类型,就无法提出有意义的继承断言。

应用环境

用户可以调用 SolverFactory 来获取原始问题的派生问题,而不是预处理的问题。上述问题的解决方案将允许我暗示用户他/她/它忘记先预处理问题,然后再传递它。现在,用户将调查他/她/它的问题,以徒劳地发现其中的错误。

C++ 模板 继承 static-assert

评论

0赞 康桓瑋 8/25/2023
您的编译器支持哪种 C++ 标准?
0赞 8/25/2023
@康桓瑋 std=c++20 会很好,但通常我是开放的。谢谢你的提问。

答:

0赞 康桓瑋 8/25/2023 #1

眼前的问题是,一个有意义的继承断言不能 在对 T 型不知情的情况下摆姿势。

在 C++20 中,您可以将概念定义为

template<typename Derived>
concept derived_from_base = requires (const Derived& d) {
  []<typename T>(const Base<T>&){}(d);
};

这要求可以将类型的对象传递给仅接受专用类参数的 lambda,该参数可用于确定类型是否是公共的,并且明确继承自模板类。DerivedBaseDerivedBase

然后,您可以将 using type-alias 限制为

template<derived_from_base TDerived>
using Mixer = Tumbler<TDerived, typename TDerived::T>;

演示

0赞 Jan Schultke 8/25/2023 #2

您可以使用:std::is_base_of

static_assert(std::is_base_of_v<Base<typename TDerived::T>, TDerived>,
              "TDerived must be derived of Base");

您还可以定义一个概念,例如:

template<typename TDerived>
concept Mixer = std::derived_from<T, Base<typename TDerived::T>>;

然后,可以将此概念用作类型约束,而不是将 a 放入类中。static_assert