partial specialization of template member function

Discussion in 'C++' started by Levent, May 10, 2005.

  1. Levent

    Levent Guest

    Hi,

    Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1):

    #include <iostream>
    template<class T, unsigned N>
    struct Foo {
    void func();
    };
    template<class T, unsigned N>
    void Foo<T,N>::func() {
    std::cout << "Primary -- "
    << "T is " << typeid(T).name() << " -- "
    << "N=" << N
    << std::endl;
    }
    template<class T>
    void Foo<T,3>::func() {
    std::cout << "Specialized for N=3 -- "
    << "T is " << typeid(T).name() << " -- "
    << std::endl;
    }

    int main() {
    Foo<double,3> d;
    Foo<int,5> i;
    d.func();
    i.func();
    return 0;
    }

    gcc compiler error: no `void Foo<T, 3>::func()' member function declared in
    class `Foo<T, 3>'
    (VC7.1 error is similar)

    On the other hand, full specialization of the member works (without
    specializing the whole class). (try replacing `template<class T> void
    Foo<T,3>::func()' with `template<> void Foo<double,3>::func()')

    If this behaviour is how it is defined in the standard, what may be a
    possible workaround to achieve partial specialization on member functions?

    thank you
    - sly.
    Levent, May 10, 2005
    #1
    1. Advertising

  2. Levent wrote:
    > Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1):
    > [..]


    Because you have to first define the partial specialisation of the
    enclosing class template.

    > On the other hand, full specialization of the member works (without
    > specializing the whole class). (try replacing `template<class T> void
    > Foo<T,3>::func()' with `template<> void Foo<double,3>::func()')
    >
    > If this behaviour is how it is defined in the standard, what may be a
    > possible workaround to achieve partial specialization on member functions?


    This is as specified. There are no partial specialisations of function
    templates, and to partially specialise a member you need to first
    partially specialise the class template.

    V
    Victor Bazarov, May 10, 2005
    #2
    1. Advertising

  3. Levent

    Levent Guest

    > VB: There are no partial specialisations of function templates ....


    When you say this you do not mean any function, right? 'cause non-member
    function templates *can* be specialized. And I should admit that partial
    specialization of member function w/o partial spec of full class is
    somewhat ill-conditioned design (can't explain why, just fells like that
    way...).

    However, I came up with a workaround: Use non-member friend template
    functions.

    Before listing the code that does this I want to note a gotcha of
    VC++7.1 (actually this is somewhat the reason I am posting this
    follow-up) which probably is a good example of how unreliable this
    compiler is.

    Here is how I implemented non-member friend template (tried to trim as
    much as I can):

    ===================================================
    #include <iostream>

    using namespace std;

    template<class T, unsigned N> class Foo;
    template<class T, unsigned N> void print(Foo<T,N> &f);

    template<class T, unsigned N>
    class Foo {
    int i;
    public:
    friend void print<>(Foo &);
    Foo(int i_) :i(i_) {};
    };

    template<class T, unsigned N>
    void print(Foo<T,N> &f) {
    cout << "Foo<" << typeid(T).name() << ", " << N << ">"
    << ".i=" << f.i << endl;
    }
    template<class T>
    void print(Foo<T,4> &f) {
    cout
    << "Specialized for N=4: "
    << "Foo<" << typeid(T).name() << ", " << 4 << ">"
    << ".i=" << f.i << endl;
    }

    int main() {
    Foo<int,4> a(9); // specialized <> instantiation
    // Foo<double,4> b(9); // another specialized <> instantiation
    Foo<double,5> c(10); // primary <> instantiation
    print(a);
    // print(b);
    print(c);
    return 0;
    }
    =====================================================

    This compiles (and runs) fine with gcc 3.3.3 and intel 8.1.

    However, with VC++7.1, it gives `print cannot access private member'
    compile error.

    Even worse happens: Commentting out the 1st and 4th lines of main() and
    uncommenting 2nd and 5th, VC++ _does_ compile... But very wrong things
    happen during run: c acts as if Foo<double,5> !!!

    can anyone confirm that this is the case?

    Victor Bazarov wrote:

    > Levent wrote:
    >
    >> Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1):
    >> [..]

    >
    >
    > Because you have to first define the partial specialisation of the
    > enclosing class template.
    >
    >> On the other hand, full specialization of the member works (without
    >> specializing the whole class). (try replacing `template<class T>
    >> void Foo<T,3>::func()' with `template<> void Foo<double,3>::func()')
    >>
    >> If this behaviour is how it is defined in the standard, what may be a
    >> possible workaround to achieve partial specialization on member
    >> functions?

    >
    >
    > This is as specified. There are no partial specialisations of function
    > templates, and to partially specialise a member you need to first
    > partially specialise the class template.
    >
    > V
    Levent, May 10, 2005
    #3
  4. Levent wrote:
    >> VB: There are no partial specialisations of function templates ....

    >
    >
    >
    > When you say this you do not mean any function, right? 'cause non-member
    > function templates *can* be specialized.


    Not partially. Only fully. There are no partial specialisations of
    function templates. Period. And when I say this I mean any function,
    member or non-member.

    You can partially specialise a class template. You can then define
    a member of that specialisation. That's not the same as partially
    specialising a function template.

    > [...]


    V
    Victor Bazarov, May 10, 2005
    #4
  5. Levent

    Levent Guest

    What I meant was *partial* specializations of template functions are
    possible. Please, take a look at this (valid) code:

    using namespace std;
    template<class T1, class T2>
    void foobar(T1 &t1,T2 &t2) {
    cout << "Primary <> instantiation -- foobar<"
    << typeid(t1).name() << "," << typeid(t2).name() << ">"
    << endl;
    }
    template<class T>
    void foobar(T &t1,double &t2) {
    cout << "Specialized <> instantiation -- foobar<"
    << typeid(t1).name() << "," << typeid(double).name() << ">"
    << endl;
    }

    int main() {
    double k,l; int i,j;
    foobar(i,j);
    foobar(k,j);
    foobar(i,k);
    return 0;
    }

    This obviously works. But maybe it is my confusion with terminology:
    What I assume as specialization is nothing but overloading, somewhat :?...

    If you are referring to the standard when you assert that

    > There are no partial specialisations of function templates. Period.


    I should take your word for it... But then, isn't it the case that
    explicit (full) specialization, is also in fact overloading?

    BTW, what do you think of the code in my previous post? Don't you think
    it is interesting that VC++7.1 fails with this?

    Victor Bazarov wrote:

    > Levent wrote:
    >
    >>> VB: There are no partial specialisations of function templates ....

    >>
    >>
    >>
    >>
    >> When you say this you do not mean any function, right? 'cause
    >> non-member function templates *can* be specialized.

    >
    >
    > Not partially. Only fully. There are no partial specialisations of
    > function templates. Period. And when I say this I mean any function,
    > member or non-member.
    >
    > You can partially specialise a class template. You can then define
    > a member of that specialisation. That's not the same as partially
    > specialising a function template.
    >
    > > [...]

    >
    > V
    Levent, May 10, 2005
    #5
  6. Levent wrote:
    > What I meant was *partial* specializations of template functions are
    > possible. Please, take a look at this (valid) code:
    >
    > using namespace std;
    > template<class T1, class T2>
    > void foobar(T1 &t1,T2 &t2) {
    > cout << "Primary <> instantiation -- foobar<"
    > << typeid(t1).name() << "," << typeid(t2).name() << ">"
    > << endl;
    > }
    > template<class T>
    > void foobar(T &t1,double &t2) {
    > cout << "Specialized <> instantiation -- foobar<"
    > << typeid(t1).name() << "," << typeid(double).name() << ">"
    > << endl;
    > }


    This is not a specialisation. It's just another template. If it were
    a specialisation, it would have <???> after the function name.

    > int main() {
    > double k,l; int i,j;
    > foobar(i,j);
    > foobar(k,j);
    > foobar(i,k);
    > return 0;
    > }
    >
    > This obviously works. But maybe it is my confusion with terminology:
    > What I assume as specialization is nothing but overloading, somewhat :?...


    Exactly. Two different templates, both contribute to overloading
    resolution.

    > If you are referring to the standard when you assert that
    >
    >> There are no partial specialisations of function templates. Period.

    >
    >
    > I should take your word for it... But then, isn't it the case that
    > explicit (full) specialization, is also in fact overloading?


    Yes.

    > BTW, what do you think of the code in my previous post? Don't you think
    > it is interesting that VC++7.1 fails with this?


    I didn't look.

    V

    P.S. Please don't top-post.
    Victor Bazarov, May 10, 2005
    #6
    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. Petre Iantu
    Replies:
    1
    Views:
    352
    Petre Iantu
    Aug 17, 2003
  2. Kai-Uwe Bux
    Replies:
    1
    Views:
    476
  3. toton
    Replies:
    1
    Views:
    612
  4. puzzlecracker
    Replies:
    2
    Views:
    286
    James Kanze
    Jan 29, 2009
  5. vj
    Replies:
    1
    Views:
    483
Loading...

Share This Page