如何在下面的代码中实现编译器从混合器中的断言返回预期的编译错误消息(参见选项 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,就无法提出有意义的继承断言。选项 A 的解决方案优于选项 B 的解决方案。
用户可以为原始问题的派生而不是预处理问题调用 SolverFactory。上述问题的解决方案将允许我提示用户他/她/它忘记先预处理问题然后再通过它。现在,用户将调查他/她/它的问题,但徒劳地发现其中的错误。
当前的问题是,有意义的继承断言不能 在不了解 T 类型的情况下提出。
在 C++20 中,您可以将概念定义为
template<typename Derived>
concept derived_from_base = requires (const Derived& d) {
[]<typename T>(const Base<T>&){}(d);
};
这要求可以将类型为
Derived
的对象传递给仅接受专门的Base
类的参数的lambda,该lambda可用于确定类型Derived
是否是公共的并且明确地继承自模板类Base
。
然后您可以将使用类型别名限制为
template<derived_from_base TDerived>
using Mixer = Tumbler<TDerived, typename TDerived::T>;