Это, безусловно, возможно; вам просто нужно быть осторожным, чтобы гарантировать, что все ветви являются взаимоисключающими, в противном случае вы получите неоднозначность.
Взгляните на Характеристики типа усиления и Boost Enable If , которые являются двумя лучшими инструментами для поддержки этого. Boost ICE (что означает Integral Constant Expression) может использоваться для объединения характеристик нескольких типов, чтобы помочь вам выполнить более сложное сопоставление типов (и гарантировать, что ваши перегрузки взаимоисключающие.
Это может быть несколько сложным и запутанным, так что вот сравнительно простой пример. Допустим, у вас есть иерархия классов:
struct Base { };
struct Derived : Base { };
и вы хотите вызвать одну перегрузку функции foo
для Base
и другую перегрузку для любого класса, производного от Base
. Первая попытка может выглядеть так:
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;
using namespace boost::type_traits;
template <typename T>
typename enable_if<is_same<Base, T>, void>::type
foo(const T&) { }
template <typename T>
typename enable_if<is_base_of<Base, T>, void>::type
foo(const T&) { }
Однако is_base_of
возвращает true, если T
является базовым классом, поэтому, если вы попытаетесь вызвать foo(Base())
, возникает двусмысленность, поскольку оба шаблона функций совпадают. Мы можем решить эту проблему, используя комбинацию черт типа и помощников Boost ICE:
template <typename T>
typename enable_if<is_same<Base, T>, void>::type
foo(const T&) { }
template <typename T>
typename enable_if<
ice_and<
is_base_of<Base, T>::value,
ice_not<is_same<Base, T>::value>::value
>, void>::type
foo(const T&) { }
Эти перегрузки являются взаимоисключающими и гарантируют отсутствие двусмысленности.
Некоторые из ваших примеров не поддерживаются (а именно, HAS_MEMBER_FUNCTION_X
; я не уверен насчет IS_TEMPLATE_CLASS_C
- в зависимости от того, что вы хотите с ним сделать, вы можете заставить что-то работать), но в целом это возможно.