Skip to content

Instantly share code, notes, and snippets.

@newmen
Last active March 7, 2020 15:52
Show Gist options
  • Save newmen/8720773 to your computer and use it in GitHub Desktop.
Save newmen/8720773 to your computer and use it in GitHub Desktop.
SFINAE in C++03 and C++11 implementations
#include <iostream>
///////////////////////////////////////////////////////////////////////////////
class Base
{
protected:
Base() {}
public:
virtual ~Base() {}
virtual void printName() const = 0;
};
class Without : public Base
{
float _f = 55.22;
public:
void printName() const override { std::cout << "Without" << std::endl; }
};
class With : public Base
{
int _value;
public:
With(int value) : _value(value) {}
void printName() const override { std::cout << "With" << std::endl; }
virtual void some() { std::cout << "some" << std::endl; }
};
///////////////////////////////////////////////////////////////////////////////
template <typename T>
class hasSomeC03
{
template <typename U, void (U::*)() = &U::some>
struct Detector { char _[2]; };
template <typename C>
static Detector<C> test(C *);
static char test(...);
public:
static const bool value =
(sizeof(test(static_cast<T *>(nullptr))) != sizeof(char));
};
// ------------------------------------------------------------------------- //
template <typename T>
class hasSomeC11
{
struct Detector {};
template <typename C>
static decltype(std::declval<C>().some()) test(const C &);
static Detector test(...);
public:
static const bool value =
!std::is_same<Detector, decltype(test(std::declval<T>()))>::value;
};
///////////////////////////////////////////////////////////////////////////////
// std::enable_if defined in C++11
template <template <class> class C, typename T>
typename std::enable_if<C<T>::value, void>::type doSomething(T *t)
{
std::cout << "T::some() exists" << std::endl;
}
template <template <class> class C, typename T>
typename std::enable_if<!C<T>::value, void>::type doSomething(T *t)
{
std::cout << "T::some() does not exist" << std::endl;
}
///////////////////////////////////////////////////////////////////////////////
int main()
{
std::cout << std::boolalpha;
std::cout << hasSomeC03<Without>::value << std::endl
<< hasSomeC03<With>::value << std::endl;
std::cout << hasSomeC11<Without>::value << std::endl
<< hasSomeC11<With>::value << std::endl;
Without without;
doSomething<hasSomeC03>(&without);
doSomething<hasSomeC11>(&without);
With with(123);
doSomething<hasSomeC03>(&with);
doSomething<hasSomeC11>(&with);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment