Reputation: 60058
C++11 allows to check, reasonably concisely, for the existence of a member: Is it possible to write a template to check for a function's existence?
Is it possible to check for the existence of a global function declaration (namespaced or not)?
Details:
In my particular case, I'd like to check if my stdio.h implementation (#include
d) defines e.g., fprintf_unlocked
(with the standard signature) and use that if it does, otherwise default to fprintf
.
Upvotes: 1
Views: 992
Reputation: 60058
I've made a hybrid traits generator macro that checks for either members or free standing functions.
This creates template traits classes that look whether a user supplied signature (first template arg) works with the name embedded in the traits class.
It looks for free-standing names if no second template param is supplied (Trait<Sig>::value
), or for a member of the second template argument if the traits template is instantiated with two arguments (Trait<Sig,ClassToSearch>::value
).
It can only search for free functions that were declared before the Traits template class was defined.
#define DEF_HAS_SIG(TraitsName, funcName) \
std::nullptr_t funcName(...); \
template<typename Sig, typename Type=void> class TraitsName { \
typedef char yes[1]; \
typedef char no [2]; \
template <typename U, U> struct TypeCheck; \
template <typename _1, typename _2 > static no &chk(...); \
template <typename _1, typename _2> static \
typename std::enable_if< std::is_same<void,_2>::value, yes&>::type chk(TypeCheck<_1, &funcName > *); \
template <typename _1, typename _2> static yes& chk(TypeCheck<_1, &_2::funcName > *); \
public: static bool const value = sizeof(chk<Sig,Type>(0)) == sizeof(yes); \
};
Upvotes: 0
Reputation: 217235
A way to check existence of function, You may create following traits:
#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature) \
template <typename U> \
class traitsName \
{ \
private: \
template<typename T, T> struct helper; \
template<typename T> \
static std::uint8_t check(helper<signature, &funcName>*); \
template<typename T> static std::uint16_t check(...); \
public: \
static \
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
}
DEFINE_HAS_SIGNATURE(has_foo, foo, T*);
DEFINE_HAS_SIGNATURE(has_bar, bar, T*);
And then test it
has_foo<void(int)>::value
Upvotes: 3