#include <type_traits>
#include <iostream>


// Our test candidates:
struct i_have_foo { void foo() const {} };
struct i_dont     { void bazinga() const {} };
int bar(std::ostream) {}


// First checker:
struct _test_has_foo {
    template<class T>
    static auto test(T* p) -> decltype(p->foo(), std::true_type());

    template<class>
    static auto test(...) -> std::false_type;
};
template<class T>
struct has_foo : decltype(_test_has_foo::test<T>(0))
{};


// Second checker:
struct _test_is_supported_by_bar {
    template<class T>
    static auto test(T* p) -> decltype(bar(*p), std::true_type());

    template<class>
    static auto test(...) -> std::false_type;
};
template<class T>
struct is_supported_by_bar : decltype(_test_is_supported_by_bar::test<T>(0))
{};


// Test:
int main()
{
    std::cout << has_foo<i_have_foo>::value << std::endl;
    std::cout << has_foo<i_dont>::value << std::endl;
    
    std::cout << std::endl;
    
    std::cout << is_supported_by_bar<std::ostream>::value << std::endl;
    std::cout << is_supported_by_bar<std::istream>::value << std::endl;
}