Re: SFINAE doesn't work ?
On Jun 3, 7:03 am, sheffm...@mail.ru wrote:
Hello everyone, what I'm trying to do is typedef detection inside a
class definition, i.e I want to have a means which could execute some
code if template type parameter is a class which has public typedef
MyType for example and the other code if the class hasn't such
typedef. I understand that it might be impossible, but still, may be
it is...
Here's what I'm trying to do:
template <class T>
void function(const T& t, int it)
{
T::iterator it2;
std::cout << "1\n";
}
template <class T>
void function(const T& t, float it)
{
std::cout << "2\n";
}
int main(int argc, char* argv[])
{
std::list<int> a;
std::bitset<6> b;
function(a, 0);
function(b, 0);
return 0;
}
What I want here is to detect if type T has typedef iterator, if it
has program should output "1", or "2" if it hasn't.
Compiling this using MSVC++2008 gives:
error C2039: 'iterator' : is not a member of 'std::bitset<_Bits>'
error C2065: 'iterator' : undeclared identifier
error C2146: syntax error : missing ';' before identifier 'it2'
error C2065: 'it2' : undeclared identifier
But why ? Compiler tried to compile void function(const T& t, int it),
it failed, because bitset doesn't have typedef iterator, the compiler
should (according to sfinae) try to compile the second overload of
'function', but it doesn't, why ?
According to this post -
http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/
6329958fe7653b16#
It's possible to make typedef detection like this:
#include <bitset>
#include <list>
#include <iostream>
template<class T> struct Void { typedef void type; };
#define DEFINED_IMPL(TypedefName) \
template <class T, class Enable = void> \
struct TypedefName##Defined \
{ \
enum { value = false }; \
}; \
template <class T> \
struct TypedefName##Defined<T, typename Void<typename
T::TypedefName>::type> \
{ \
enum { value = true }; \
} \
#define DEFINED(TypeName, TypedefName) \
TypedefName##Defined<TypeName>::value \
DEFINED_IMPL(iterator);
DEFINED_IMPL(value_type);
template <bool Cond, class T> struct EnableIf {};
template <class T> struct EnableIf<true, T> { typedef T type; };
template <class T>
typename EnableIf<DEFINED(T, iterator) && DEFINED(T, value_type),
void>::type function(const T& t)
{
std::cout << "iterator and value_type defined" << std::endl;
}
template <class T>
typename EnableIf<!(DEFINED(T, iterator) && DEFINED(T, value_type)),
void>::type function(const T& t)
{
std::cout << "iterator and value_type not defined" << std::endl;
}
struct MyS
{
typedef int iterator;
};
void main()
{
std::list<int> a;
std::bitset<6> b;
int c;
std::list< std::list<int> > d;
std::string e;
MyS f;
function(a);
function(b);
function(c);
function(d);
function(e);
function(f);
}
So the problem is solved, but! It's not just typedef detection I
wanted, it would be great to have conditional compiling using
templates, i.e without preprocessor, what I want is:
....
void function(...)
{
//Some code here
}
....
void function(...)
{
//This code gets compiled only if previous overload failed to compile
}
My first post was an attempt to create such conditional compiling, but
it's incorrect, could anyone tell me, is it possible in C++ ?
I think that theoretically it's possible, because of sfinae...
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]