Я не знаю, в чем проблема с вашей реализацией has_clear
, но ее можно заменить этой значительно упрощенной, работающей реализацией с использованием более современных функций SFINAE / type_traits:
template<typename T, typename Enable = void>
struct has_clear : std::false_type {};
template<typename T>
struct has_clear<
T,
std::enable_if_t<
std::is_same_v<decltype(&T::clear), void (T::*)()> ||
std::is_same_v<decltype(&T::clear), void (T::*)() noexcept>
>
> : std::true_type {};
И для удобство:
template<typename T>
constexpr bool has_clear_v = has_clear<T>::value;
В сочетании с if constexpr
вы можете очень просто и просто решить, какой путь к коду запускать, когда другие не смогут скомпилироваться. Например:
template<typename T>
void maybe_clear(T t){
if constexpr (has_clear_v<T>){
// only compiled when T has a non-static clear() method
std::cout << "clearing " << typeid(T).name() << '\n';
t.clear();
} else {
// only compiled when T does not have a non-static clear() method
std::cout << "doing nothing with " << typeid(T).name() << '\n';
}
}
Я считаю, что это позволяет добиться того, чего вы хотите, но исправить, если я неправильно понял. Это решение стоит C ++ 17.
Live Demo