Trouble specializing a member function in a template class

Discussion in 'C++' started by Jeff, Nov 19, 2003.

  1. Jeff

    Jeff Guest

    /* --------------------------------------------------------------------------
    Hello,

    I was experimenting with class templates and specializing member
    functions and came across a simple problem which I can't figure out.
    I have a simple class C with 2 template member objects, and a function
    print() that prints the value of these objects. I defined a
    specialization of print() for C<string, char> which is called
    correctly. Then I wanted to define a specialization of print() that
    would be called for C<class T, int>, where T is any type. I couldn't
    get this code to compile, let alone run, and tried various ways to
    make it work. The full source is below.

    Is there a nice solution to this problem? I read somewhere (can't
    recall where) that you can't specialize member functions for classes
    without specializing the whole class, and yet the C<string,
    char>::print() specialization works.

    Jeff
    ---------------------------------------------------------------------------
    */


    #include <iostream>
    #include <string>
    using namespace std;


    template<class A, class B>
    class C {
    public:
    C(A a, B b) : a_(a), b_(b) {}

    A a_;
    B b_;
    void print() const;
    };


    // Template definition of print()
    template<class A, class B> void C<A, B>::print() const
    { cout << "Output: " << a_ << ", " << b_ << endl; }


    // Full specialization of print() for <string, char> types
    template<> void C<string, char>::print() const {
    cout << "C<string, char> output: " << a_ << " ... " << b_ << endl;
    }


    // Trouble here ---------------------------------------------
    // the following partial specialization gives the compiler error:
    // a.cpp:33: no `void C<A, int>::print() const' member function
    declared in class `C<A, int>'
    // a.cpp:33: template definition of non-template `void C<A,
    int>::print() const'
    // (using GCC 3.2)

    // if B is type int, call this...
    //template<class A, int> //doesn't work
    //template<class A, class B> // doesn't work
    template<class A> // doesn't work
    void
    C<A, int>::print() const {
    cout << "C<A, int> output: ";
    for (int i=0; i<b_; ++i) { cout << a_ << endl; }
    cout << endl;
    }
    // end of Trouble -------------------------------------------


    int main() {
    // calls template definition, prints "Output: a, 1.23456"
    C<char, float> myC('a', 1.23456);
    myC.print();
    cout << endl;

    // calls full specialization successfully, prints "C<string, char>
    output: hello there ... b"
    C<string, char> C2("hello there", 'z');
    C2.print();
    cout << endl;

    // should call partial specialization, want it to print "C<A, int>
    output: boo!boo!boo!boo!boo!"
    C<string, int> pc("boo!", 5);
    pc.print();
    cout << endl;

    return 0;
    }
    Jeff, Nov 19, 2003
    #1
    1. Advertising

  2. Jeff wrote in news::

    > I was experimenting with class templates and specializing member
    > functions and came across a simple problem which I can't figure out.
    > I have a simple class C with 2 template member objects, and a function
    > print() that prints the value of these objects. I defined a
    > specialization of print() for C<string, char> which is called
    > correctly. Then I wanted to define a specialization of print() that
    > would be called for C<class T, int>, where T is any type. I couldn't
    > get this code to compile, let alone run, and tried various ways to
    > make it work. The full source is below.
    >


    Your problem is that you are trying to create a partial specialization
    of a function (non-static member in this case, but that doesn't matter).
    For some reason this is not allowed by the language (possibly the
    standards committee thought overloading was enough). The workaround
    as always is to add another layey of indirection (see below).

    > Is there a nice solution to this problem? I read somewhere (can't
    > recall where) that you can't specialize member functions for classes
    > without specializing the whole class, and yet the C<string,
    > char>::print() specialization works.


    Yup explicit specialization's (template <>) are allowed.

    >


    #include <iostream>
    #include <typeinfo>

    struct example
    {
    template < typename U, typename V >
    void patialy_specialized( U const &u, V const &v );

    };

    /* helper class
    */
    template < typename U, typename V >
    struct example_patialy_specialized
    {
    static void apply( example * that, U const &u, V const &v )
    {
    std::cerr
    << "default version "
    << typeid( U ).name()
    << " - "
    << typeid( V ).name()
    << "\n"
    ;
    }
    };

    /* defenition of template method, indirects through the
    "helper" above or (importantly) one of its specializations.
    */
    template < typename U, typename V >
    inline void example::patialy_specialized( U const &u, V const &v)
    {
    return example_patialy_specialized< U, V >::apply( this, u, v );
    }

    /* demo specialization of the "helper"
    */
    template < typename U >
    struct example_patialy_specialized< U, int >
    {
    static void apply( example * that, U const &arg, int )
    {
    std::cerr << "U int version " << typeid( U ).name() << "\n";
    }
    };

    int main()
    {
    example ex;
    double d = 1;

    ex.patialy_specialized( d, d ); // default
    ex.patialy_specialized( d, 1 ); // partial specialization
    }

    HTH

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Nov 19, 2003
    #2
    1. Advertising

  3. Jeff

    Jeff Guest

    Thanks Rob, got it. I guess I'd need to make the
    example_patialy_specialized<U, V> template a friend inside the
    example<U, V> template to access any of the private member data. Kind
    of unfortunate, it clutters up what seems to be a fairly simple
    problem (mind you, I have no need for it yet, just testing)... but
    that's templates for you.

    Thanks again, a big help.
    Jeff
    Jeff, Nov 20, 2003
    #3
    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. Simon G Best
    Replies:
    2
    Views:
    552
    Simon G Best
    Dec 29, 2006
  2. Rahul
    Replies:
    8
    Views:
    385
    Lionel B
    Jul 16, 2007
  3. Igor R.
    Replies:
    4
    Views:
    478
    Igor R.
    Nov 11, 2009
  4. John
    Replies:
    3
    Views:
    328
    James Kanze
    Aug 17, 2010
  5. m0shbear
    Replies:
    2
    Views:
    340
Loading...

Share This Page