SFINAE help

Discussion in 'C++' started by Tim H, Aug 18, 2009.

  1. Tim H

    Tim H Guest

    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 H, Aug 18, 2009
    #1
    1. Advertising

  2. 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?


    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
    };

    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
    Maxim Yegorushkin, Aug 18, 2009
    #2
    1. Advertising

  3. Maxim Yegorushkin wrote:
    > [..]
    > 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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 18, 2009
    #3
  4. Victor Bazarov wrote:
    > Maxim Yegorushkin wrote:
    >> [..]
    >> 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
    Maxim Yegorushkin, Aug 18, 2009
    #4
  5. Tim H

    Tim Hockin Guest

    On Aug 18, 6:08 am, Maxim Yegorushkin <>
    wrote:
    > 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?

    > 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?

    >      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_0/libs/type_traits/doc/html/boost_...
    >
    > Max
    Tim Hockin, Aug 18, 2009
    #5
  6. Tim Hockin wrote:
    > On Aug 18, 6:08 am, Maxim Yegorushkin <>
    > wrote:
    >> 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.


    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().

    --
    Max
    Maxim Yegorushkin, Aug 18, 2009
    #6
  7. Tim H

    Tim Hockin Guest

    On Aug 18, 10:18 am, Maxim Yegorushkin <>
    wrote:
    > Tim Hockin wrote:
    > > On Aug 18, 6:08 am, Maxim Yegorushkin <>
    > > wrote:
    > >> 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.

    >
    > 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.


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

    Thanks


    >  > 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().
    >
    > --
    > Max
    Tim Hockin, Aug 18, 2009
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Collingbourne

    problem with SFINAE applied to class methods

    Peter Collingbourne, Jul 1, 2004, in forum: C++
    Replies:
    8
    Views:
    448
    Pete Becker
    Jul 4, 2004
  2. Replies:
    3
    Views:
    1,653
    Attila Feher
    Feb 8, 2005
  3. Clark S. Cox III

    Using SFINAE with constructors

    Clark S. Cox III, Sep 9, 2005, in forum: C++
    Replies:
    2
    Views:
    368
    Howard Hinnant
    Sep 9, 2005
  4. christopher diggins

    SFINAE problem.

    christopher diggins, Sep 26, 2005, in forum: C++
    Replies:
    4
    Views:
    447
    christopher diggins
    Sep 26, 2005
  5. SFINAE

    , Apr 26, 2006, in forum: C++
    Replies:
    4
    Views:
    463
    n2xssvv g02gfr12930
    Apr 26, 2006
Loading...

Share This Page