CRTP - "abstract" 静态接口中的方法

CRTP - "abstract" method in static interface

我正在尝试找出一些方法来强制执行基础 CRTP class 和派生的 CRTP 之间的契约。使用动态多态性时,可以简单地做:

struct foo{
    virtual bar() = 0;
};

并且编译器会确保在派生class时实现了方法bar,否则它会(或多或少)给出有意义的错误信息。现在我能用 CRTP 获得的最好结果是这样的:

template<class Derived>
struct base {
    void stuff(){
        static_cast<Derived &>(*this).baz();  
    }
};

这将以某种方式在派生 class 中强制执行 baz,但并不是真正可读,也不清楚基础和派生 class 之间的契约是什么。所以我的问题是,有没有办法做得更好?我知道 C++20 概念并且它们将是这种情况的完美解决方案,但我正在寻找 C++11/C++14 解决方案以使其尽可能干净。

由于在定义基础时派生的 class 总是不完整,我使用的一种解决方案是使用默认模板参数延迟 "concept check" 实例化:

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 概念不会解决这个特殊问题,延迟概念检查仍然是必要的。好处是编译错误会更清楚

Demo