SFINAE and explicit instantiation

G

greek_bill

Hi,

I have a template function for which I use SFINAE to restrict one of
the parameters. Then I also have a partial specialization[1] of this
function.I would like to provide an explicit instantiation of the
partially specialized version, but my compiler (VC8) complains because
it fails the SFINAE version.

[1] I just realized as I was typing this that I'm using partial
_function_ specialization. I'm sure I remember reading somewhere that
this isn't allowed. VC8 and gcc are quite happy with it though.
Anyway...

Code as follows :

// Used for the SFINAE condition

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

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


// SFINAE helper

template<bool allow, class T>
struct RestrictTo {};

template<class T>
struct RestrictTo<true, T> { typedef T type; };


// SFINAE function template

class Foo {};

template<class A, class T>
typename RestrictTo<IsSameType<T,int>::value, void>::type
Func(A, T)
{}

// Partially specialized version
template<class A>
void Func(A, float)
{}

// Explicit instantiation
template void Func(float, float);


This compiles fine with g++. VC8 says :

error C2794: 'type' : is not a member of any direct or indirect base
class of 'RestrictTo<allow,T>'
with
[
allow=false,
T=void
]


As I understand it, if I was to just call Func(1.0f, 2.0f) then SFINAE
would kick in an reject the first version, leading to the specialized
version to be picked up. If I didn't have SFINAE then there would be
an ambiguity.

It seems though that this rule isn't follow if I try to do an explicit
instantiation. It looks like the compiler thinks that I'm trying to
explicitly instantiate the SFINAE version with an argument that
violates the condition I specified.

Interestingly, qualifying the explicit specialization with <float>,
i.e.

template void Func<float>(float, float);


doesn' t help matters at all. I was hoping that if I supply <float>
that would be enough of a hint to the compiler that I'm trying to
instantiate a template with just one parameter.


gcc 4.3.2 compiles this fine by the way.


Thanks,

Bill
 
G

greek_bill

On a side note, the above is not actually a partial template function
specialization. It is function overloading. if it was a specialization
(which it couldn't be) it would need to be of the form

template<class A>
void Func<A, float>(A, float)
{}


In any case, this is a side note I think. The original problem is not
affected (I think)!
 
F

Francesco

On a side note, the above is not actually a partial template function
specialization. It is function overloading. if it was a specialization
(which it couldn't be) it would need to be of the form

 template<class A>
void Func<A, float>(A, float)
{}

In any case, this is a side note I think. The original problem is not
affected (I think)!

Hi,
maybe I'm missing something, but from your code it seems that you want
2 functions:
- one that works with a templated argument and an int and
- one that works with a templated argument and a float
so I don't get why you're using SFINAE for that.
Maybe the problem is different so sorry in advance if I sound silly,
but isn't the following doing what you want?
Regards,
Francesco

P.S.
there could be ambiguity if you try to instantiate with a double as
2nd argument but that's another story...

//code
#include <iostream>

template< typename T >
void F( T, int )
{ std::cout << "INT VERSION" << std::endl; }

template< typename T >
void F( T, float )
{ std::cout << "FLOAT VERSION" << std::endl; }

template void F( float, float );

int main()
{
F( 10, 10 );
F( 10, 20.20f );
std::cin.get();
}
//end code
 
G

greek_bill

Ugh, I can see why you'd suggest that. I'm afraid that during the
process of simplifying the code to this bare bones example the
usefulness of the SFINAE construct got lost. In the original code that
I was trying to compile the SFINAE construct had a valid purpose and
the code above is the minimal amount of code that I could put together
that reproduces the problem.

As it turns out I've worked around this problem (I expressed the
RestrictTo condition as a compile time assert in the body of the
function), but it would still be interesting to find out why I was
getting the above problem.

Thanks,

Bill
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top