SFINAE help

T

Tim H

I have a template class 'Property' that has a ValueType typedef in it.

I have a method of another class that looks like this:

template<class Tkey>
const typename Tkey::ValueType &GetProperty() const { ... }

I want to support Properties with void ValueType. I added a
specialization of Property and that works. what fails is when code
calls the above GetProperty<VoidProperty>() method. I get a "no
matching function" error (g++).

It looks like SFINAE is correctly determining that a 'const void &' is
an error. The error message is not very helpful, though.

How can I use SFINAE (or other tricks) to make calls to
GetProperty<VoidProperty>() blow up in a more obvious manner?
 
M

Maxim Yegorushkin

Tim said:
I have a template class 'Property' that has a ValueType typedef in it.

I have a method of another class that looks like this:

template<class Tkey>
const typename Tkey::ValueType &GetProperty() const { ... }

I want to support Properties with void ValueType. I added a
specialization of Property and that works. what fails is when code
calls the above GetProperty<VoidProperty>() method. I get a "no
matching function" error (g++).

It looks like SFINAE is correctly determining that a 'const void &' is
an error. The error message is not very helpful, though.

How can I use SFINAE (or other tricks) to make calls to
GetProperty<VoidProperty>() blow up in a more obvious manner?

Tim said:
> I have a template class 'Property' that has a ValueType typedef in it.
>
> I have a method of another class that looks like this:
>
> template<class Tkey>
> const typename Tkey::ValueType &GetProperty() const { ... }
>
> I want to support Properties with void ValueType. I added a
> specialization of Property and that works. what fails is when code
> calls the above GetProperty<VoidProperty>() method. I get a "no
> matching function" error (g++).
>
> It looks like SFINAE is correctly determining that a 'const void &' is
> an error. The error message is not very helpful, though.
>
> How can I use SFINAE (or other tricks) to make calls to
> GetProperty<VoidProperty>() blow up in a more obvious manner?

There is no SFINAE involved because you instantiate the function template
_explicitly_.

SFINAE works while the compiler is building a set of viable function overloads.
In doing so it also tries to _implicitly_ instantiate function templates. If
function template instantiation fails when the template arguments are
substituted with particular types, that Substitution Failure Is Not An Error,
the function template is simply disregarded and no compiler error produced.

Your example can be made to work without SFINAE. Something like that:

template<class T>
struct MakeRefToConst
{
typedef T const& type;
};

template<>
struct MakeRefToConst<void>
{
typedef void type; // don't make references to void
};

template<class Tkey>
typename MakeRefToConst<typename Tkey::ValueType>::type GetProperty();

struct A
{
typedef int ValueType;
};

struct B
{
typedef void ValueType;
};

int main()
{
GetProperty<A>();
GetProperty<B>();
}

Instead of MakeRefToConst<> you can use boost type traits.
http://www.boost.org/doc/libs/1_39_...html/boost_typetraits/category/transform.html

Max
 
V

Victor Bazarov

Maxim said:
[..]
SFINAE works while the compiler is building a set of viable function
overloads. In doing so it also tries to _implicitly_ instantiate
function templates. If function template instantiation fails when the
template arguments are substituted with particular types, that
Substitution Failure Is Not An Error, the function template is simply
disregarded and no compiler error produced.

That's only if there is something else the compiler can use instead. If
there is nothing else, the compiler is still going to give an error.

Just my $0.02...

V
 
M

Maxim Yegorushkin

Victor said:
Maxim said:
[..]
SFINAE works while the compiler is building a set of viable function
overloads. In doing so it also tries to _implicitly_ instantiate
function templates. If function template instantiation fails when the
template arguments are substituted with particular types, that
Substitution Failure Is Not An Error, the function template is simply
disregarded and no compiler error produced.

That's only if there is something else the compiler can use instead. If
there is nothing else, the compiler is still going to give an error.

This error happens after the set of viable overloads has been built, regardless
of SFINAE.

When the compiler discovers that the set of viable overloads has no items it
spits something like "error: no matching function for call to ..."

Max
 
T

Tim Hockin

Tim H wrote:

 > I have a template class 'Property' that has a ValueType typedef in it.
 >
 > I have a method of another class that looks like this:
 >
 >       template<class Tkey>
 >       const typename Tkey::ValueType &GetProperty() const { .... }
 >
 > I want to support Properties with void ValueType.  I added a
 > specialization of Property and that works.  what fails is when code
 > calls the above GetProperty<VoidProperty>() method.  I get a "no
 > matching function" error (g++).
 >
 > It looks like SFINAE is correctly determining that a 'const void &' is
 > an error.  The error message is not very helpful, though.
 >
 > How can I use SFINAE (or other tricks) to make calls to
 > GetProperty<VoidProperty>() blow up in a more obvious manner?

There is no SFINAE involved because you instantiate the function template
_explicitly_.

SFINAE works while the compiler is building a set of viable function overloads.
In doing so it also tries to _implicitly_ instantiate function templates. If
function template instantiation fails when the template arguments are
substituted with particular types, that Substitution Failure Is Not An Error,
the function template is simply disregarded and no compiler error produced.

Your example can be made to work without SFINAE. Something like that:

     template<class T>
     struct MakeRefToConst
     {
         typedef T const& type;
     };

     template<>
     struct MakeRefToConst<void>
     {
         typedef void type; // don't make references to void
     };
cute!

     template<class Tkey>
     typename MakeRefToConst<typename Tkey::ValueType>::type GetProperty();

This is a class method, in my situation, which may matter. The
question I have is - what does the body of this function look like?
The generic implementation of this ends with

return specific->GetValue();

on which the compiler complains about "return-statement with a value,
in function returning 'void'"

How can I provide an alternate body for void ValueType that does not
try to return a value?
 
M

Maxim Yegorushkin

Tim said:
This is a class method, in my situation, which may matter.

This is about the return value, so it does not make a difference whether it is a
standalone or member function.
> The
question I have is - what does the body of this function look like?

This is for you to decide.
The generic implementation of this ends with

return specific->GetValue();

on which the compiler complains about "return-statement with a value,
in function returning 'void'"

It means that GetProperty() return type is void, but the return type of
GetValue() is not void.
> How can I provide an alternate body for void ValueType that does not
> try to return a value?

In this case an alternative body may be unnecessary, since static_cast<> can
cast any value to void. So, your last statement can do:

return static_cast<
typename MakeRefToConst<
typename Tkey::ValueType
>::type>(specific->GetValue());

If Tkey::ValueType happens to be void this cast just discards the return value
of specific->GetValue().
 
T

Tim Hockin

This is about the return value, so it does not make a difference whether it is a
standalone or member function.

 > The


This is for you to decide.




It means that GetProperty() return type is void, but the return type of
GetValue() is not void.

Ahh, that was the key. I missed one place where I cut-and-pasted.
Fixed and it works.

Thanks
 

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

SFINAE 4
SFINAE and explicit instantiation 3
iterator_traits and SFINAE 7
SFINAE not applying as expected. 1
what happened to my sfinae? 3
SFINAE 4
Trying to apply SFINAE 10
about SFINAE usage 15

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top