restrict_to, enable_if, etc

G

greek_bill

With regards to using Boost enable_if and similar SFINAE constructs,
is it right that you can only put an enable_if on the return type or
as an additional parameter? Why is that?

The following doesn't compile (VC8 and gcc 3.4.4) :

namespace Test
{

template<typename T, typename U>
struct IsSameType
{
enum { value = false };
};

template<typename T>
struct IsSameType<T,T>
{
enum { value = true };
};

//------------------------------------------------------------------

struct Foo
{
// Doesn't compile
template<class T>
void Func(typename enable_if_c<!IsSameType<T, int>::value, T>::type
t)
{}

// But this does...
template<class T>
typename enable_if_c<!IsSameType<T, int>::value, void>::type Func(T
t)
{}

void Func(int i)
{}
};

void FooFunc()
{
Foo f;

// Should go to non-template version
f.Func(5);

// Should go to template version
char* p;
f.Func(p);
}

}


Thanks,

Vassilis
 
G

Gennaro Prota

greek_bill said:
With regards to using Boost enable_if and similar SFINAE constructs,
is it right that you can only put an enable_if on the return type or
as an additional parameter? Why is that?

The following doesn't compile (VC8 and gcc 3.4.4) :

namespace Test
{

template<typename T, typename U>
struct IsSameType
{
enum { value = false };
};

template<typename T>
struct IsSameType<T,T>
{
enum { value = true };
};

//------------------------------------------------------------------

struct Foo
{
// Doesn't compile
template<class T>
void Func(typename enable_if_c<!IsSameType<T, int>::value, T>::type
t)
{}

// But this does...
template<class T>
typename enable_if_c<!IsSameType<T, int>::value, void>::type Func(T
t)
{}

void Func(int i)
{}
};
[more code snipped]

This is really odd. Please, copy-and-paste the exact code you are trying
to compile (the above can't be it, of course).
 
G

greek_bill

while copying and pasting I missed out the definition of enable_if_c,
which I have it as :

template<bool b, class T>
struct enable_if_c
{
typedef T type;
};

template<class T>
struct enable_if_c<false, T> {};



but other than that it the above code should be enough to illustrate
the problem. You need to comment out one or the other template
implementation of Func().
 
G

Gennaro Prota

greek_bill said:
You need to comment out one or the other template
implementation of Func().

That's the info you should have given :)

About your original question, you *can* have one function parameter and
enable_if on it (its type), but you'll usually face another issue:
something like

foo< ... >::

is a so-called "non-deduced context". A "classical" example is:

template< typename T >
struct identity
{
typedef T type ;
} ;

template< typename T >
void
f( typename identity< T >::type t )
{
}

int main()
{
f( 1 ) ; // can't deduce
}

So, even if you had simply

struct Foo
{
template< typename T >
void Func( typename enable_if_c< true, T >::type )
{
}
} ;

it wouldn't work for your p (FWIW, f.Func< char * >( p ) would,
instead). On the contrary, your second template gives a way to deduce an
argument for T; and, after all arguments are deduced, they are
substituted in non-deduced contexts (later, SFINAE applies).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top