Template class member function specialization

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • James Aguilar

    #1

    Template class member function specialization

    Guys,

    When I specialize a template class member function (I.e. a member
    function of a template class) based on that class' type, bad things
    happen. Here's some code:

    ---- test_header.h
    #ifndef TEST_HEADER_H
    #define TEST_HEADER_H

    #include <iostream>

    template <typename T>
    class Test
    {
    public:
    void out();
    };

    template <>
    void
    Test<char>::out ()
    {
    std::cout << "I am a char!\n";
    }

    template <typename T>
    void
    Test<T>::out()
    {
    std::cout << "I am a T!\n";
    }

    #endif
    ----
    ---- test_main.cpp
    #include "test_heade r.h"

    int main()
    {
    Test<chart1;
    Test<intt2;

    t1.out();
    t2.out();

    return 0;
    }
    ----
    ---- test_other.cpp
    #include "test_heade r.h"

    int test()
    {
    Test<chart;
    Test<intt2;

    t.out();
    t2.out();
    }
    ----
    ---- g++-4.1.2 reports:
    ../test_other.o: In function `Test<char>::ou t()':
    .../test_header.h:1 5: multiple definition of `Test<char>::ou t()'
    ../test_main.o:../test_header.h:1 5: first defined here
    ----

    But I thought I was supposed to put template functions and their
    specializations in the header file. It works if I inline it, but I
    don't *want* to inline it. In my real system, the function is a little
    larger.

    Any help from the gurus out there?

    Grace be with you,
    James Aguilar

  • amparikh@gmail.com

    #2
    Re: Template class member function specialization


    James Aguilar wrote:
    Guys,
    >
    When I specialize a template class member function (I.e. a member
    function of a template class) based on that class' type, bad things
    happen. Here's some code:
    >
    ---- test_header.h
    #ifndef TEST_HEADER_H
    #define TEST_HEADER_H
    >
    #include <iostream>
    >
    template <typename T>
    class Test
    {
    public:
    void out();
    };
    >
    template <>
    void
    Test<char>::out ()
    {
    std::cout << "I am a char!\n";
    }
    >
    template <typename T>
    void
    Test<T>::out()
    {
    std::cout << "I am a T!\n";
    }
    >
    #endif
    ----
    ---- test_main.cpp
    #include "test_heade r.h"
    >
    int main()
    {
    Test<chart1;
    Test<intt2;
    >
    t1.out();
    t2.out();
    >
    return 0;
    }
    ----
    ---- test_other.cpp
    #include "test_heade r.h"
    >
    int test()
    {
    Test<chart;
    Test<intt2;
    >
    t.out();
    t2.out();
    }
    ----
    ---- g++-4.1.2 reports:
    ./test_other.o: In function `Test<char>::ou t()':
    ../test_header.h:1 5: multiple definition of `Test<char>::ou t()'
    ./test_main.o:../test_header.h:1 5: first defined here
    ----
    >
    But I thought I was supposed to put template functions and their
    specializations in the header file. It works if I inline it, but I
    don't *want* to inline it. In my real system, the function is a little
    larger.
    >
    Any help from the gurus out there?
    >
    Grace be with you,
    James Aguilar
    Your class Test is a template class. Your function out is not a
    template member function.

    So

    1>Either you first need to explicity specialize your class

    or

    2>Make your member function "out" to be a template member function and
    then specialize it.

    class Test
    {
    public:
    template <typename T>
    void out();
    };

    template<>
    void Test::Out<char> ()
    {
    }

    Comment

    • James Aguilar

      #3
      Re: Template class member function specialization

      amparikh@gmail. com wrote:
      >
      Your class Test is a template class. Your function out is not a
      template member function.
      >
      So
      >
      1>Either you first need to explicity specialize your class
      >
      or
      >
      2>Make your member function "out" to be a template member function and
      then specialize it.
      I certainly can't do the second. The class I'm actually writing is an
      iterator over a specialized container. But I want the iterator's
      operator *() function to do something special, but only when it is
      templatized by char. You're saying I have to reimplement the entire
      class in order to change just one method? Or am I misreading you
      somehow?

      Yours,
      James Aguilar

      Comment

      • Victor Bazarov

        #4
        Re: Template class member function specialization

        James Aguilar wrote:
        Guys,
        >
        When I specialize a template class member function (I.e. a member
        function of a template class) based on that class' type, bad things
        happen. Here's some code:
        >
        ---- test_header.h
        #ifndef TEST_HEADER_H
        #define TEST_HEADER_H
        >
        #include <iostream>
        >
        template <typename T>
        class Test
        {
        public:
        void out();
        };
        >
        template <>
        What if you just drop this "tempalate <>" thing? What you're trying
        to do is to define the body of a particular function. It's not
        a specialisation. Of course, since you stuck it into a header you
        probably want to declare it "inline" while you're at it. Or move it
        into an implemenation file to avoid multiple definition errors.
        void
        Test<char>::out ()
        {
        std::cout << "I am a char!\n";
        }
        >
        template <typename T>
        void
        Test<T>::out()
        {
        std::cout << "I am a T!\n";
        }
        >
        #endif
        ----
        ---- test_main.cpp
        #include "test_heade r.h"
        >
        int main()
        {
        Test<chart1;
        Test<intt2;
        >
        t1.out();
        t2.out();
        >
        return 0;
        }
        ----
        ---- test_other.cpp
        #include "test_heade r.h"
        >
        int test()
        {
        Test<chart;
        Test<intt2;
        >
        t.out();
        t2.out();
        }
        ----
        ---- g++-4.1.2 reports:
        ./test_other.o: In function `Test<char>::ou t()':
        ../test_header.h:1 5: multiple definition of `Test<char>::ou t()'
        ./test_main.o:../test_header.h:1 5: first defined here
        ----
        >
        But I thought I was supposed to put template functions and their
        specializations in the header file. It works if I inline it, but I
        don't *want* to inline it. In my real system, the function is a
        little larger.
        So, don't inline it. Declare it in the header (without the 'template<>')
        and then define it in one of the translation units.
        >
        Any help from the gurus out there?
        See above.

        V
        --
        Please remove capital 'A's when replying by e-mail
        I do not respond to top-posted replies, please don't ask


        Comment

        • amparikh@gmail.com

          #5
          Re: Template class member function specialization


          James Aguilar wrote:
          amparikh@gmail. com wrote:

          Your class Test is a template class. Your function out is not a
          template member function.

          So

          1>Either you first need to explicity specialize your class

          or

          2>Make your member function "out" to be a template member function and
          then specialize it.
          >
          I certainly can't do the second. The class I'm actually writing is an
          iterator over a specialized container. But I want the iterator's
          operator *() function to do something special, but only when it is
          templatized by char. You're saying I have to reimplement the entire
          class in order to change just one method? Or am I misreading you
          somehow?
          then just take out the template < from the top of the specialization.
          >
          Yours,
          James Aguilar

          Comment

          Working...