Template member function default argument

Discussion in 'C++' started by Mike Alexeev, May 21, 2004.

  1. Mike Alexeev

    Mike Alexeev Guest

    What is the correct syntax for default values to member function
    templates?
    Here is my example:
    1 struct A
    2 {
    3 typedef int typeA;
    4 };
    5
    6 struct B
    7 {
    8 template<class Y>
    9 void f(typename Y::typeA = typename Y::typeA()) {}
    10 };
    11
    12 int main()
    13 {
    14 B t;
    15 t.f<A>(4);
    16 return 0;
    17 }

    Sun Workshop 6.2 compiler complains about line 9 with the following
    message: Operand expected instead of "typename".

    G++ 3.1.1 handles it without any problem.
    Any help would greatly appreciated.
    Mike Alexeev, May 21, 2004
    #1
    1. Advertising

  2. Mike Alexeev wrote in news:
    in comp.lang.c++:

    > What is the correct syntax for default values to member function
    > templates?
    > Here is my example:
    > 1 struct A
    > 2 {
    > 3 typedef int typeA;
    > 4 };
    > 5
    > 6 struct B
    > 7 {


    typedef typename Y::typeA typeA;

    > 8 template<class Y>
    > 9 void f(typename Y::typeA = typename Y::typeA()) {}


    void f(typeA = typeA()) {}


    > 10 };
    > 11
    > 12 int main()
    > 13 {
    > 14 B t;
    > 15 t.f<A>(4);
    > 16 return 0;
    > 17 }
    >
    > Sun Workshop 6.2 compiler complains about line 9 with the following
    > message: Operand expected instead of "typename".
    >
    > G++ 3.1.1 handles it without any problem.
    > Any help would greatly appreciated.
    >


    IIUC the second typename isn't required as typename Y::typeA()
    *isn't* a declaration. OTOH I couldn't find a compiler that
    rejects it either.

    If removing the typename doesn't work with g++ 3.1.1 then use
    the above (inline) workaround.

    HTH.

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, May 21, 2004
    #2
    1. Advertising

  3. Mike Alexeev

    Mike Alexeev Guest

    Rob Williscroft <> wrote in message news:<Xns94F038478DB60ukcoREMOVEfreenetrtw@130.133.1.4>...
    > Mike Alexeev wrote in news:
    > in comp.lang.c++:
    >
    > > What is the correct syntax for default values to member function
    > > templates?
    > > Here is my example:
    > > 1 struct A
    > > 2 {
    > > 3 typedef int typeA;
    > > 4 };
    > > 5
    > > 6 struct B
    > > 7 {

    >
    > typedef typename Y::typeA typeA;
    >
    > > 8 template<class Y>
    > > 9 void f(typename Y::typeA = typename Y::typeA()) {}

    >
    > void f(typeA = typeA()) {}
    >
    >
    > > 10 };
    > > 11
    > > 12 int main()
    > > 13 {
    > > 14 B t;
    > > 15 t.f<A>(4);
    > > 16 return 0;
    > > 17 }
    > >
    > > Sun Workshop 6.2 compiler complains about line 9 with the following
    > > message: Operand expected instead of "typename".
    > >
    > > G++ 3.1.1 handles it without any problem.
    > > Any help would greatly appreciated.
    > >

    >
    > IIUC the second typename isn't required as typename Y::typeA()
    > *isn't* a declaration. OTOH I couldn't find a compiler that
    > rejects it either.
    >
    > If removing the typename doesn't work with g++ 3.1.1 then use
    > the above (inline) workaround.
    >
    > HTH.
    >
    > Rob.


    Rob,
    Unfortunately your solution won't work because it is a member function
    template and you can not do typedef outside the template. This was my
    original problem.
    template<class Y>
    void f(typename Y::typeA = typename Y::typeA()) {}

    Mike
    Mike Alexeev, May 21, 2004
    #3
  4. Mike Alexeev wrote in news:
    in comp.lang.c++:

    >> IIUC the second typename isn't required as typename Y::typeA()
    >> *isn't* a declaration. OTOH I couldn't find a compiler that
    >> rejects it either.
    >>
    >> If removing the typename doesn't work with g++ 3.1.1 then use
    >> the above (inline) workaround.
    >>
    >> HTH.
    >>
    >> Rob.

    >
    > Rob,
    > Unfortunately your solution won't work because it is a member function


    Sorry I missed that, but my solution was to remove the second typename
    which should still work, have you tried it ? does g++ 3.1.1 require the
    typename ?, neither of g++ 3.2.2 or g++ 3.4 do.

    > template and you can not do typedef outside the template. This was my
    > original problem.
    > template<class Y>
    > void f(typename Y::typeA = typename Y::typeA()) {}
    >


    If you still need a workaround:

    template < typename T >
    struct default_arg
    {
    static value() { return T(); }
    };


    struct B
    {
    template < typename Y >
    void f(
    typename Y::typeA arg = default_arg< typename Y::typeA >::value()
    )
    {
    }
    };

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, May 22, 2004
    #4
  5. Mike Alexeev

    Siemel Naran Guest

    (Mike Alexeev) wrote in message

    > Here is my example:
    > 1 struct A
    > 2 {
    > 3 typedef int typeA;
    > 4 };
    > 5
    > 6 struct B
    > 7 {
    > 8 template<class Y>
    > 9 void f(typename Y::typeA = typename Y::typeA()) {}


    The above looks fine, but I've seen some compilers get confused with
    code like this. Try the fix mentioned below for line 15, and if that
    doesn't work, then consider this: The compiler does not do template
    argument deduction for nested types, so why not move the template
    <class Y> from B::f to B? But if you really need it you can write a
    second function that forwards to the first.

    8 template<class Y>
    9 void f(typename Y::typeA) {}
    10 template<class Y>
    11 void f() { typedef typename Y::typeA typeA; return
    f(typeA()); }

    Also, when my compiler Borland C++ 6 wouldn't accept code like what
    you have, I turned f into a functor-like class, so it allowed me to
    typedef typename Y::typeA typeA as if it were a member of the class,
    so that in operator() I could say operator()(typeA = typeA()). This
    is much like Rob's approach.


    > 10 };
    > 11
    > 12 int main()
    > 13 {
    > 14 B t;
    > 15 t.f<A>(4);


    It should be

    t.template f<A>(4);

    G++ 3.1 accepts either version, but it should accept only the latter.

    > 16 return 0;
    > 17 }
    Siemel Naran, May 22, 2004
    #5
  6. Mike Alexeev

    Mike Alexeev Guest

    Rob Williscroft <> wrote in message news:<Xns94F1751133664ukcoREMOVEfreenetrtw@130.133.1.4>...
    > Mike Alexeev wrote in news:
    > in comp.lang.c++:
    >
    > >> IIUC the second typename isn't required as typename Y::typeA()
    > >> *isn't* a declaration. OTOH I couldn't find a compiler that
    > >> rejects it either.
    > >>
    > >> If removing the typename doesn't work with g++ 3.1.1 then use
    > >> the above (inline) workaround.
    > >>
    > >> HTH.
    > >>
    > >> Rob.

    > >
    > > Rob,
    > > Unfortunately your solution won't work because it is a member function

    >
    > Sorry I missed that, but my solution was to remove the second typename
    > which should still work, have you tried it ? does g++ 3.1.1 require the
    > typename ?, neither of g++ 3.2.2 or g++ 3.4 do.
    >
    > > template and you can not do typedef outside the template. This was my
    > > original problem.
    > > template<class Y>
    > > void f(typename Y::typeA = typename Y::typeA()) {}
    > >

    >
    > If you still need a workaround:
    >
    > template < typename T >
    > struct default_arg
    > {
    > static value() { return T(); }
    > };
    >
    >
    > struct B
    > {
    > template < typename Y >
    > void f(
    > typename Y::typeA arg = default_arg< typename Y::typeA >::value()
    > )
    > {
    > }
    > };
    >
    > Rob.


    Rob,
    Thanks for the workaround. It works perfectly.
    As far as second typename goes G++ 3.1.1 handles it without any
    problem. I am going to try it with the 3.4 version as well. It was the
    problem with Sun Workshop 6.2 compiler (CC) which I was not able to
    compile both with second typename or without it.
    Mike
    Mike Alexeev, May 22, 2004
    #6
  7. Siemel Naran wrote in news:
    in comp.lang.c++:

    >> 11
    >> 12 int main()
    >> 13 {
    >> 14 B t;
    >> 15 t.f<A>(4);

    >
    > It should be
    >
    > t.template f<A>(4);
    >
    > G++ 3.1 accepts either version, but it should accept only the latter.
    >
    >> 16 return 0;

    >


    Nope it should accept the former, 't' *isn't* a dependant
    name it's a 'B', so its member 'f' isn't a dependant name.

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, May 23, 2004
    #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.

Share This Page