Проблема в вашем коде состоит в том, что вы проверяете, что класс имеет метод, который принимает в качестве первого аргумента константную ссылку на объект того же класса
template <class T>
static std::true_type testSignature(bool (T::*)(const T&, double) const);
// .......................................^...........^ same class
но внутри Derived
вы определяете метод, который получает объект другого класса (Base
)
// ...VVVVVVV object is Derived
class Derived : public Base {
public:
// same interface as base class
bool approx_equal(const Base& other, double tolerance) const;
// .....................^^^^ method accept Base
};
Возможное решение - расслабить тест в HasApproxEqualMethod
, чтобы принять также объекты разных классов
template <class T, class U>
static std::true_type testSignature(bool (T::*)(const U&, double) const);
// now class and argument are different...^...........^
Этот способ также удовлетворен
static_assert(HasApproxEqualMethod<Derived>().value == true, "fail Derived");
Если вы хотите вообще избежать проверки подписи, вы можете попробовать нечто подобное
template <typename T>
constexpr auto haemHelper (T const &, int)
-> decltype( &T::approx_equal, std::true_type{} );
template <typename T>
constexpr std::false_type haemHelper (T const &, long);
template <typename T>
using HasApproxEqualMethod = decltype( haemHelper(std::declval<T>(), 0) );
но, таким образом, HasApproxEqualMethod<T>
равен std::true_type
также, когда T
имеет метод approx_equal
с совершенно другой сигнатурой или также когда approx_equal
является простым членом (переменной).