Легко написать шаблон, который будет детектировать наличие конкретного элемента в пределах типа с помощью void_t
:Определение присутствия произвольного члена
#include <type_traits>
// This comes from cppreference
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
// primary template handles types that have no ::aMember
template< class T, class = void_t<> >
struct has_aMember : std::false_type { };
// specialization recognizes types that do have a ::aMember
template< class T >
struct has_aMember<T, void_t<decltype(T::aMember)>> : std::true_type { };
Теперь, если я хочу, чтобы обнаружить, является ли какой-либо другой член нет, я должен был бы скопировать и вставить шаблоны детектора и просто изменить aMember
к otherMember
:
template< class T, class = void_t<> >
struct has_otherMember : std::false_type { };
template< class T >
struct has_otherMember<T, void_t<decltype(T::otherMember)>> : std::true_type { };
Я хотел бы избежать этого копирования-вставки и передать имя элемента в качестве параметра для более общего варианта шаблон обнаружения:
template< class T, class member, class = void_t<> >
struct has_arbitrary_member : std::false_type { };
template< class T, class member >
struct has_arbitrary_member<T, void_t<decltype(T::member)>> : std::true_type { };
так, что я мог бы использовать этот has_arbitrary_member
, передавая тип и имя элемента в качестве параметра шаблона:
std::cout << has_arbitrary_member<MyType, aMember>();
std::cout << has_arbitrary_member<MyType, otherMember>();
Однако, с определением набросал я выше, это не будет компилировать , Есть ли другой способ реализовать такую функциональность?
Лучшее, что вы можете сделать, это что-то вроде ['std :: experimental :: is_detected'] (http://en.cppreference.com/w/cpp/experimental/is_detected). –
Что значит «нравится»? Блок кода * выше * * аналогичен * этим двум строкам. Каковы ваши жесткие требования и как блок кода выше их не соответствует вашим требованиям? Я мог бы написать лучшую версию вашего кода выше (скажем, с 'is_detected'), но я не имел бы способа, если это то, что вы хотите. – Yakk
@Yakk Я добавил предложение в конец вопроса, чтобы уточнить мое намерение более четко. Конечно, void_t не является требованием, хотя я вижу, что 'is_detected' реализуется с использованием' void_t'. Помогает ли это? – Rostislav