#include <type_traits>

template<typename...>
using void_type = void;

template <typename, typename, typename = void_type<>>
struct CheckHelper: std::false_type {};

template <typename T, typename Base>
struct CheckHelper<T, Base, void_type<typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type>> : std::true_type {};

template <typename T, typename Base, typename = void_type<>>
struct CheckFun: CheckHelper<T, Base> {};

template <typename T, typename Base>
struct CheckFun<T, Base, void_type<typename std::enable_if<!std::is_same<decltype(&T::fun), decltype(&Base::fun)>::value, void>::type>> : std::true_type {};

template<typename T = std::nullptr_t>
class Base {
public:
	virtual void fun() {
		static_assert(CheckFun<T, Base>::value, "Class T shoul override fun");

	}
};

class Derived1: public Base<Derived1> {
public:
	void fun() override {

	}
};

class Derived2: public Base<Derived2> {
};


int main() {
	Base<> b{};
	Derived1 d1{};
	Derived2 d2{};
	d2.fun();
}