I am trying to leave in struct A
one function foo
(prints 0) if its parameter have template method isA<void>
and another (prints 1) if haven't. This code (reduced to minimal example below) compiles (tried with gcc 6.1.0 and clang-3.9.0 with explicit --std=c++14
option) and runs.
But it prints 1, though, I am sure, that it shall print 0. I wonder where am I wrong, but real question is: how to make this work correct?
Please only C++14 solutions.
#include <type_traits>
#include <iostream>
#include <utility>
using std::enable_if;
using std::declval;
using std::true_type;
using std::false_type;
using std::cout;
template<int M>
struct ObjectX
{
template<typename C>
bool isA() { return false; }
};
struct XX : ObjectX<23456> {
int af;
};
template <typename ObjType> using has_dep = decltype(declval<ObjType>().template isA<void>());
template <typename, typename = void>
struct has_isa : public false_type {};
template <typename ObjType>
struct has_isa<ObjType, has_dep<ObjType> > : public true_type {};
template<typename ObjType>
struct A
{
template<typename T = void>
typename enable_if<has_isa<ObjType>::value, T>::type
foo() {
cout << "called foo #0" << "\n";
}
template<typename T = void>
typename enable_if<!has_isa<ObjType>::value, T>::type
foo() {
cout << "called foo #1" << "\n";
}
};
int
main()
{
A<XX> axx;
// XX().template isA<void>(); -- to check, that we can call it and it exists
axx.foo();
return 0;
}