Łatwo jest napisać szablon, który wykrywa obecność konkretnego członka ramach typu używając void_t
:wykrywania obecności dowolnego członka
#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 { };
Teraz, jeśli chcę, aby wykryć, czy jakiś inny członek jest obecny, musiałbym skopiować i wkleić szablony detektora i wystarczy zmienić aMember
do 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 { };
chciałbym tego uniknąć kopiowania i wklejania i podać nazwę użytkownika jako parametr do bardziej generycznej wersji szablon detekcja:
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 { };
tak, że mogę korzystać z tego has_arbitrary_member
przekazując typ i nazwę użytkownika jako parametr szablonu:
std::cout << has_arbitrary_member<MyType, aMember>();
std::cout << has_arbitrary_member<MyType, otherMember>();
Jednak z definicji ja przygotowanego powyżej, nie będzie to skompilować . Czy jest jakiś inny sposób na wdrożenie takiej funkcjonalności?
Najlepsze, co możesz zrobić, to coś w rodzaju ['std :: experimental :: is_detected'] (http://en.cppreference.com/w/cpp/experimental/is_detected). –
Co masz na myśli mówiąc "lubię"? Blok kodu * powyżej * jest * jak * te dwie linie. Jakie są wasze twarde wymagania i w jaki sposób blok kodu nad nimi nie spełnia waszych wymagań? Mógłbym napisać lepszą wersję twojego kodu powyżej (powiedzmy, z 'is_detected'), ale nie miałbym sposobu, jeśli tego właśnie chcesz. – Yakk
@Yakk Dodałem zdanie na końcu pytania, aby sprecyzować moje zamiary. Oczywiście void_t nie jest wymogiem, chociaż widzę, że 'is_detected' jest zaimplementowane za pomocą samego' void_t'. czy to pomaga? – Rostislav