SFINAE

Discussion in 'C++' started by none, Mar 28, 2008.

  1. none

    none Guest

    I am trying to understand SFINAE based on this wiki page:

    http://en.wikipedia.org/wiki/SFINAE



    // Defines return type to be void for all types
    // besides int.
    template<typename T>
    struct can_use_f {
    typedef void type;
    };

    template<>
    struct can_use_f<int> {

    typedef int type;
    };

    // function with return type ::type.
    template<typename T>
    typename can_use_f<T>::type f(T const &);

    int main() {

    f(1);
    f(1.);

    }



    I have made a slight modification so if f(1) is called f should have
    return type int. But it gives the error:

    /tmp/cclJK0dJ.o: In function `main':
    bob.cpp:(.text+0x95): undefined reference to `can_use_f<int>::type
    f<int>(int const&)'
    bob.cpp:(.text+0xa5): undefined reference to `can_use_f<double>::type
    f<double>(double const&)'
    collect2: ld returned 1 exit status

    Is this the correct execution steps:

    1) f(T const &) is called.
    2) the return type is decided based on the template parameter.
    3) if T != int return type is void. If T = int return type should be int
    (this does not work).
    none, Mar 28, 2008
    #1
    1. Advertising

  2. none" <""johs\"@(none) wrote:
    > I am trying to understand SFINAE based on this wiki page:
    >
    > http://en.wikipedia.org/wiki/SFINAE
    >
    >
    >
    > // Defines return type to be void for all types
    > // besides int.
    > template<typename T>
    > struct can_use_f {
    > typedef void type;
    > };
    >
    > template<>
    > struct can_use_f<int> {
    >
    > typedef int type;
    > };
    >
    > // function with return type ::type.
    > template<typename T>
    > typename can_use_f<T>::type f(T const &);
    >
    > int main() {
    >
    > f(1);
    > f(1.);
    >
    > }
    >
    >
    >
    > I have made a slight modification so if f(1) is called f should have
    > return type int. But it gives the error:
    >
    > /tmp/cclJK0dJ.o: In function `main':
    > bob.cpp:(.text+0x95): undefined reference to `can_use_f<int>::type
    > f<int>(int const&)'
    > bob.cpp:(.text+0xa5): undefined reference to `can_use_f<double>::type
    > f<double>(double const&)'
    > collect2: ld returned 1 exit status


    Of course it does. You declared the 'f' template function, but
    you haven't given it a body!

    > Is this the correct execution steps:
    >
    > 1) f(T const &) is called.
    > 2) the return type is decided based on the template parameter.
    > 3) if T != int return type is void. If T = int return type should be
    > int (this does not work).


    WHAT does not work? The Wikipedia article is not about that, is it?

    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, Mar 28, 2008
    #2
    1. Advertising

  3. none

    Davis King Guest

    On Mar 27, 8:14 pm, none <""johs\"@(none)"> wrote:
    > I am trying to understand SFINAE based on this wiki page:
    >
    > http://en.wikipedia.org/wiki/SFINAE
    >
    > // Defines return type to be void for all types
    > // besides int.
    > template<typename T>
    > struct can_use_f {
    > typedef void type;
    >
    > };
    >
    > template<>
    > struct can_use_f<int> {
    >
    > typedef int type;
    >
    > };
    >
    > // function with return type ::type.
    > template<typename T>
    > typename can_use_f<T>::type f(T const &);
    >
    > int main() {
    >
    > f(1);
    > f(1.);
    >
    > }
    >
    > I have made a slight modification so if f(1) is called f should have
    > return type int. But it gives the error:
    >
    > /tmp/cclJK0dJ.o: In function `main':
    > bob.cpp:(.text+0x95): undefined reference to `can_use_f<int>::type
    > f<int>(int const&)'
    > bob.cpp:(.text+0xa5): undefined reference to `can_use_f<double>::type
    > f<double>(double const&)'
    > collect2: ld returned 1 exit status
    >
    > Is this the correct execution steps:
    >
    > 1) f(T const &) is called.
    > 2) the return type is decided based on the template parameter.
    > 3) if T != int return type is void. If T = int return type should be int
    > (this does not work).


    You get that linker error because you haven't defined the body of your
    f() function. You need to change it to be at least this:
    template<typename T>
    typename can_use_f<T>::type f(T const &) {} // note the addition of
    {}


    However, this isn't SFINAE. It would be (sort of) if you hadn't added
    that typedef int type; declaration. But I think this example from
    wikipedia is pretty confusing. I would recommend you read
    http://www.boost.org/libs/utility/enable_if.html for a much clearer
    explanation of what SFINAN is all about and why you might want to use
    it.

    -Davis
    Davis King, Mar 28, 2008
    #3
  4. none

    James Kanze Guest

    On Mar 28, 1:14 am, none <""johs\"@(none)"> wrote:
    > I am trying to understand SFINAE based on this wiki page:


    You'd probably be better off using an orignal source. Say the
    Jusuttis and Vandevoorde. The Wikipedia is NOT the place to
    learn how to use technical concepts.

    > http://en.wikipedia.org/wiki/SFINAE


    > // Defines return type to be void for all types
    > // besides int.
    > template<typename T>
    > struct can_use_f {
    > typedef void type;
    > };


    > template<>
    > struct can_use_f<int> {
    > typedef int type;
    > };


    > // function with return type ::type.
    > template<typename T>
    > typename can_use_f<T>::type f(T const &);


    > int main() {
    > f(1);
    > f(1.);
    > }


    There's no SFINAE in your example. SFINAE occurs during
    template argument type deduction, and is used to eliminate
    certain functions from the overload set (so they won't be
    considered and chosen later). Since there's no failure to
    deduce template arguments in your code, there's no SFINAE.

    Note that your code doesn't correspond to that in the Wikipedia
    article, since you've ensured that template argument deduction
    will always work. (I'm not sure that the Wikipedia example is
    well chosen, however. The usual use of SFINAE is exactly what
    the article says in its first sentence: "used when resolving
    overloaded functions or templates". Providing an example which
    doesn't involve overloading, but uses SFINAE to provoke a later
    error, seems rather contradictory. At the very least, some
    explination as to how this is used for concept checking would
    have been in order.)

    > I have made a slight modification so if f(1) is called f should have
    > return type int. But it gives the error:


    > /tmp/cclJK0dJ.o: In function `main':
    > bob.cpp:(.text+0x95): undefined reference to `can_use_f<int>::type
    > f<int>(int const&)'
    > bob.cpp:(.text+0xa5): undefined reference to `can_use_f<double>::type
    > f<double>(double const&)'
    > collect2: ld returned 1 exit status


    That's because you haven't provided an implementation for the
    function.

    > Is this the correct execution steps:


    > 1) f(T const &) is called.
    > 2) the return type is decided based on the template parameter.
    > 3) if T != int return type is void. If T = int return type should be int
    > (this does not work).


    Of course it does. Just provide an implementation of the
    function, and there's no problem. (Note that your error
    messages come from the linker.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Mar 28, 2008
    #4
  5. none

    Guest

    On Mar 28, 6:24 am, James Kanze <> wrote:
    > On Mar 28, 1:14 am, none <""johs\"@(none)"> wrote:

    [...]
    > >http://en.wikipedia.org/wiki/SFINAE

    [...]
    > I'm not sure that the Wikipedia example is
    > well chosen, however.

    [...]

    FWIW, I've edited the Wikipedia article. It could still use at least
    two examples (one actually demonstrating a use of SFINAE to discover a
    type property, and another one showing enable_if).


    (And thanks for the plug!)

    Daveed
    , Mar 31, 2008
    #5
    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:
    465
    Pete Becker
    Jul 4, 2004
  2. Replies:
    3
    Views:
    1,663
    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:
    373
    Howard Hinnant
    Sep 9, 2005
  4. christopher diggins

    SFINAE problem.

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

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

Share This Page