używam następujący znanego podejścia na podstawie SFINAE:
#define TYPE_SUPPORTS(ClassName, Expr) \
template<typename U> \
struct ClassName \
{ \
private: \
template<typename> \
static constexpr std::false_type test(...); \
\
template<typename T = U> \
static decltype((Expr), std::true_type{}) test(int) ; \
\
public: \
static constexpr bool value = decltype(test<U>(0))::value; \
};
Głównym celem makra jest uproszczenie dodawania kontroli typów. Makro definiuje klasę, która umożliwia wykonanie dowolnego sprawdzenia dla typu T
.
Jako przykład, aby sprawdzić, czy std::begin()
można nazwać dla typu:
namespace detail
{
TYPE_SUPPORTS(SupportsBegin, std::begin(std::declval<T>()))
}
template<typename T>
bool supportsBegin()
{
return detail::SupportsBegin<T>::value;
}
Oczywiście, detail
nazw i funkcja otoki są cały cukier syntaktyczny, ale poprawić składnię nieco na boku dzwoniącego .
Czy jest jakiś cel pytania lub jesteś po prostu ciekawy – aaronman