我正在尝试找到某种方法来在基本CRTP类和派生类之间强制执行合同。使用动态多态性时,只需执行以下操作即可:
struct foo{
virtual bar() = 0;
};
并且编译器将确保方法bar
是在派生类中实现的,否则它将给出(或多或少)有意义的错误消息。现在,我可以使用CRTP获得的最好的结果是这样的:
template<class Derived>
struct base {
void stuff(){
static_cast<Derived &>(*this).baz();
}
};
这将以某种方式强制在派生类中实施baz
的实现,但并不太可读,并清除基类和派生类之间的约定。所以我的问题是,有没有办法更好地做到这一点?我知道C ++ 20概念,它们对于这种情况将是完美的解决方案,但是我正在寻找C ++ 11 / C ++ 14解决方案以使其尽可能简洁。
答案 0 :(得分:2)
由于定义基数时派生类总是不完整,因此我使用的一种解决方案是使用默认的模板参数来延迟“概念检查”实例化:
template<class T>
using has_baz = decltype(std::declval<T&>().baz());
template<class Derived>
struct base{
template<class T = Derived, has_baz<T>* =nullptr>
void stuff(){/*...*/}
};
请注意,c ++ 20概念将无法解决此特殊问题,因此仍然有必要延迟概念检查。好处是编译错误会更清楚。