Static Member Function Template Specialization

Discussion in 'C++' started by mike b, Oct 14, 2007.

  1. mike b

    mike b Guest

    Hello everyone, thanks in advance for your help. I'm new to C++
    templates and have run into some issues using member function
    templates. I have a shared library containing templates that I'm
    trying to use from an executable, compile using gcc 4.1.2. Everything
    works fine until I try specializing one of the static member function
    templates in a non-template class. I have a feeling I'm messing up
    something obvious so before I post a bunch of code does the following
    look correct? Thanks.

    --- Shared Library (Arrays.h) ---

    namespace example {
    class Arrays {
    public:
    template<class T> static int compareItems(T *a1, T *a2, int length);
    protected:
    Arrays() {};
    };

    template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    printf("Calling generic function.\n");
    return 1;
    }

    template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    length) {
    printf("Calling char specialization.\n");
    return 0;
    }
    }
     
    mike b, Oct 14, 2007
    #1
    1. Advertising

  2. On 2007-10-14 18:38, mike b wrote:
    > Hello everyone, thanks in advance for your help. I'm new to C++
    > templates and have run into some issues using member function
    > templates. I have a shared library containing templates that I'm
    > trying to use from an executable, compile using gcc 4.1.2. Everything
    > works fine until I try specializing one of the static member function
    > templates in a non-template class. I have a feeling I'm messing up
    > something obvious so before I post a bunch of code does the following
    > look correct? Thanks.
    >
    > --- Shared Library (Arrays.h) ---
    >
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int length);
    > protected:
    > Arrays() {};
    > };
    >
    > template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    > printf("Calling generic function.\n");
    > return 1;
    > }
    >
    > template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    > length) {
    > printf("Calling char specialization.\n");
    > return 0;
    > }
    > }


    I can see nothing wrong with it (except using printf and not including
    <stdio.h>). What error messages are you getting and how are you trying
    to use the function?

    --
    Erik Wikström
     
    =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=, Oct 14, 2007
    #2
    1. Advertising

  3. mike b

    Lance Diduck Guest

    On Oct 14, 12:38 pm, mike b <> wrote:
    > Hello everyone, thanks in advance for your help. I'm new to C++
    > templates and have run into some issues using member function
    > templates. I have a shared library containing templates that I'm
    > trying to use from an executable, compile using gcc 4.1.2. Everything
    > works fine until I try specializing one of the static member function
    > templates in a non-template class. I have a feeling I'm messing up
    > something obvious so before I post a bunch of code does the following
    > look correct? Thanks.
    >
    > --- Shared Library (Arrays.h) ---
    >
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int length);
    > protected:
    > Arrays() {};
    >
    > };
    >
    > template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    > printf("Calling generic function.\n");
    > return 1;
    >
    > }
    >
    > template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    > length) {
    > printf("Calling char specialization.\n");
    > return 0;
    >
    >
    >
    > }
    > }- Hide quoted text -
    >
    > - Show quoted text -

    Your specialization should be inside the example:Arrays class, not
    outside it.
    namespace example {
    class Arrays {
    public:
    template<class T> static int compareItems(T *a1, T *a2, int
    length);
    static int compareItems(char*a1, char *a2, int
    length);
    };


    You cant add a new specialization once the class declaration is
    closed. If compareItems were a namespace level declaration, then you
    can reopen the namespace and add a new specialization later.
    Lance
     
    Lance Diduck, Oct 14, 2007
    #3
  4. mike b wrote:
    > Hello everyone, thanks in advance for your help. I'm new to C++
    > templates and have run into some issues using member function
    > templates. I have a shared library containing templates that I'm
    > trying to use from an executable, compile using gcc 4.1.2. Everything
    > works fine until I try specializing one of the static member function
    > templates in a non-template class. I have a feeling I'm messing up
    > something obvious so before I post a bunch of code does the following
    > look correct? Thanks.
    >
    > --- Shared Library (Arrays.h) ---
    >
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int length);
    > protected:
    > Arrays() {};
    > };
    >
    > template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    > printf("Calling generic function.\n");
    > return 1;
    > }
    >
    > template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    > length) {
    > printf("Calling char specialization.\n");
    > return 0;
    > }
    > }


    This below compiles fine and does what I think you expect. What problem
    are you having ?

    #include <cstdio>
    #include <iostream>

    namespace example {
    class Arrays {
    public:
    template<class T> static int compareItems(T *a1, T *a2, int length);
    Arrays() {};
    };

    template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    std::printf("Calling generic function.\n");
    return 1;
    }

    template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    length) {
    std::printf("Calling char specialization.\n");
    return 0;
    }
    }

    int main()
    {
    std::cout << example::Arrays::compareItems( (short*)0, (short*)0, 0
    ) << "\n";
    std::cout << example::Arrays::compareItems( (char*)0, (char*)0, 0 )
    << "\n";
    }
     
    Gianni Mariani, Oct 14, 2007
    #4
  5. On 2007-10-14 20:16, Lance Diduck wrote:
    > On Oct 14, 12:38 pm, mike b <> wrote:
    >> Hello everyone, thanks in advance for your help. I'm new to C++
    >> templates and have run into some issues using member function
    >> templates. I have a shared library containing templates that I'm
    >> trying to use from an executable, compile using gcc 4.1.2. Everything
    >> works fine until I try specializing one of the static member function
    >> templates in a non-template class. I have a feeling I'm messing up
    >> something obvious so before I post a bunch of code does the following
    >> look correct? Thanks.
    >>
    >> --- Shared Library (Arrays.h) ---
    >>
    >> namespace example {
    >> class Arrays {
    >> public:
    >> template<class T> static int compareItems(T *a1, T *a2, int length);
    >> protected:
    >> Arrays() {};
    >>
    >> };
    >>
    >> template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    >> printf("Calling generic function.\n");
    >> return 1;
    >>
    >> }
    >>
    >> template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    >> length) {
    >> printf("Calling char specialization.\n");
    >> return 0;
    >>
    >>
    >>
    >> }
    >> }- Hide quoted text -
    >>
    >> - Show quoted text -

    > Your specialization should be inside the example:Arrays class, not
    > outside it.
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int
    > length);
    > static int compareItems(char*a1, char *a2, int
    > length);
    > };


    Actually, what you are suggesting is not a specialisation, but declaring
    a non-parametrised function taking care of the special case. Which, to
    my knowledge, will work just as well but there are probably some subtle
    details that make specialised parametrised functions different from
    normal functions.

    --
    Erik Wikström
     
    =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=, Oct 14, 2007
    #5
  6. On Oct 14, 11:16 pm, Lance Diduck <> wrote:
    > On Oct 14, 12:38 pm, mike b <> wrote:
    > Your specialization should be inside the example:Arrays class, not
    > outside it.
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int
    > length);
    > static int compareItems(char*a1, char *a2, int
    > length);
    > };

    IIRR, a template specialization will always start with the word
    "template". Hence, the above (non-template) function is surely not a
    specialization of the template function.


    >
    > You cant add a new specialization once the class declaration is
    > closed.


    14.7.3(2) says:
    "An explicit specialization of a member function, member class or
    static data member of a class template shall be declared in the
    namespace of which the class template is a member"

    Which means that new specializations can be added in the same
    namespace.

    -N
     
    Neelesh Bodas, Oct 14, 2007
    #6
  7. mike b

    mike b Guest

    On Oct 14, 2:16 pm, Lance Diduck <> wrote:
    > On Oct 14, 12:38 pm, mike b <> wrote:
    >
    > > Hello everyone, thanks in advance for your help. I'm new to C++
    > > templates and have run into some issues using member function
    > > templates. I have a shared library containing templates that I'm
    > > trying to use from an executable, compile using gcc 4.1.2. Everything
    > > works fine until I try specializing one of the static member function
    > > templates in a non-template class. I have a feeling I'm messing up
    > > something obvious so before I post a bunch of code does the following
    > > look correct? Thanks.

    >
    > > --- Shared Library (Arrays.h) ---

    >
    > > namespace example {
    > > class Arrays {
    > > public:
    > > template<class T> static int compareItems(T *a1, T *a2, int length);
    > > protected:
    > > Arrays() {};

    >
    > > };

    >
    > > template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    > > printf("Calling generic function.\n");
    > > return 1;

    >
    > > }

    >
    > > template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    > > length) {
    > > printf("Calling char specialization.\n");
    > > return 0;

    >
    > > }
    > > }- Hide quoted text -

    >
    > > - Show quoted text -

    >
    > Your specialization should be inside the example:Arrays class, not
    > outside it.
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int
    > length);
    > static int compareItems(char*a1, char *a2, int
    > length);
    > };
    >
    > You cant add a new specialization once the class declaration is
    > closed. If compareItems were a namespace level declaration, then you
    > can reopen the namespace and add a new specialization later.
    > Lance


    I tried this but it doesn't automatically call my specialization. Do
    I need to call overloaded implementations of the function from inside
    the generic implementation? So basically don't use specialization at
    all, use overloading from within the single generic implementation?
     
    mike b, Oct 14, 2007
    #7
  8. mike b

    mike b Guest

    On Oct 14, 2:16 pm, Gianni Mariani <> wrote:
    > mike b wrote:
    > > Hello everyone, thanks in advance for your help. I'm new to C++
    > > templates and have run into some issues using member function
    > > templates. I have a shared library containing templates that I'm
    > > trying to use from an executable, compile using gcc 4.1.2. Everything
    > > works fine until I try specializing one of the static member function
    > > templates in a non-template class. I have a feeling I'm messing up
    > > something obvious so before I post a bunch of code does the following
    > > look correct? Thanks.

    >
    > > --- Shared Library (Arrays.h) ---

    >
    > > namespace example {
    > > class Arrays {
    > > public:
    > > template<class T> static int compareItems(T *a1, T *a2, int length);
    > > protected:
    > > Arrays() {};
    > > };

    >
    > > template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    > > printf("Calling generic function.\n");
    > > return 1;
    > > }

    >
    > > template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    > > length) {
    > > printf("Calling char specialization.\n");
    > > return 0;
    > > }
    > > }

    >
    > This below compiles fine and does what I think you expect. What problem
    > are you having ?
    >
    > #include <cstdio>
    > #include <iostream>
    >
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int length);
    > Arrays() {};
    >
    > };
    >
    > template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    > std::printf("Calling generic function.\n");
    > return 1;
    >
    > }
    >
    > template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    > length) {
    > std::printf("Calling char specialization.\n");
    > return 0;
    >
    > }
    > }
    >
    > int main()
    > {
    > std::cout << example::Arrays::compareItems( (short*)0, (short*)0, 0
    > ) << "\n";
    > std::cout << example::Arrays::compareItems( (char*)0, (char*)0, 0 )
    > << "\n";
    >
    > }


    The problem only occurs when code is separated into multiple binaries,
    a shared lib and executable, with multiple users in the app.
     
    mike b, Oct 14, 2007
    #8
  9. mike b wrote:
    > On Oct 14, 2:16 pm, Gianni Mariani <> wrote:

    ....
    > The problem only occurs when code is separated into multiple binaries,
    > a shared lib and executable, with multiple users in the app.



    Are definitions of all template functions in every compilation unit ?
    (i.e. included into every binary's source in question ?) If not, that's
    your problem.
     
    Gianni Mariani, Oct 14, 2007
    #9
  10. mike b

    mike b Guest

    On Oct 14, 6:13 pm, Gianni Mariani <> wrote:
    > mike b wrote:
    > > On Oct 14, 2:16 pm, Gianni Mariani <> wrote:

    > ...
    > > The problem only occurs when code is separated into multiple binaries,
    > > a shared lib and executable, with multiple users in the app.

    >
    > Are definitions of all template functions in every compilation unit ?
    > (i.e. included into every binary's source in question ?) If not, that's
    > your problem.


    I defined my entire template class in the header file (.h) so it
    should be making it into every compilation unit. Is there something
    aside from that I need to do?
     
    mike b, Oct 15, 2007
    #10
  11. mike b

    mike b Guest

    On Oct 14, 12:38 pm, mike b <> wrote:
    > Hello everyone, thanks in advance for your help. I'm new to C++
    > templates and have run into some issues using member function
    > templates. I have a shared library containing templates that I'm
    > trying to use from an executable, compile using gcc 4.1.2. Everything
    > works fine until I try specializing one of the static member function
    > templates in a non-template class. I have a feeling I'm messing up
    > something obvious so before I post a bunch of code does the following
    > look correct? Thanks.
    >
    > --- Shared Library (Arrays.h) ---
    >
    > namespace example {
    > class Arrays {
    > public:
    > template<class T> static int compareItems(T *a1, T *a2, int length);
    > protected:
    > Arrays() {};
    >
    > };
    >
    > template<class T> int Arrays::compareItems(T *a1, T *a2, int length) {
    > printf("Calling generic function.\n");
    > return 1;
    >
    > }
    >
    > template<> int Arrays::compareItems<char>(char *a1, char *a2, int
    > length) {
    > printf("Calling char specialization.\n");
    > return 0;
    >
    > }
    > }


    Sincere thanks to everyone who responded, the problem has been
    solved. The issue it seems is that I was defining my member
    specializations in the header but only a declaration for the
    specialization is allowed in the header, the actual implementation
    must go in the implementation file, .cpp. So here is the change to
    make the code work:

    --- Arrays.h ---

    namespace example {
    class Arrays : public Object {
    public:
    template<class T> static int compareItems(const T a1[], const
    T a2[], const int length);
    };

    // I was defining the function here but only the declaration goes here
    template<> int Arrays::compareItems(const char a1[], const char a2[],
    const int length);

    template<class T> int compareItems(const T a1[], const T a2[], const
    int length) {
    // Generic implementation goes here.
    }
    }


    --- Arrays.cpp ---

    // This was in the header file before and was causing the problems,
    moving it here solved it.
    template<> int hydro::Arrays::compareItems(const char a1[], const char
    a2[], const int length) {
    return strncmp(a1, a2, length);
    }

    --- END ---
     
    mike b, Oct 15, 2007
    #11
  12. mike b wrote:
    ....
    > Sincere thanks to everyone who responded, the problem has been
    > solved. The issue it seems is that I was defining my member
    > specializations in the header but only a declaration for the
    > specialization is allowed in the header, the actual implementation
    > must go in the implementation file, .cpp.


    Sounds strange. What errors were you getting ?
     
    Gianni Mariani, Oct 16, 2007
    #12
  13. mike b

    mike b Guest

    On Oct 16, 3:45 pm, Gianni Mariani <> wrote:
    > mike b wrote:
    >
    > ...
    >
    > > Sincere thanks to everyone who responded, the problem has been
    > > solved. The issue it seems is that I was defining my member
    > > specializations in the header but only a declaration for the
    > > specialization is allowed in the header, the actual implementation
    > > must go in the implementation file, .cpp.

    >
    > Sounds strange. What errors were you getting ?


    I was getting errors about my specialization being defined multiple
    times. This was with GCC 4.
     
    mike b, Oct 17, 2007
    #13
  14. mike b wrote:
    > On Oct 16, 3:45 pm, Gianni Mariani <> wrote:
    >> mike b wrote:
    >>
    >> ...
    >>
    >>> Sincere thanks to everyone who responded, the problem has been
    >>> solved. The issue it seems is that I was defining my member
    >>> specializations in the header but only a declaration for the
    >>> specialization is allowed in the header, the actual implementation
    >>> must go in the implementation file, .cpp.

    >> Sounds strange. What errors were you getting ?

    >
    > I was getting errors about my specialization being defined multiple
    > times. This was with GCC 4.



    Declare the template as "inline" as see if you get the same errors.
     
    Gianni Mariani, Oct 17, 2007
    #14
  15. mike b

    Greg Herlihy Guest

    On Oct 17, 1:17 am, Gianni Mariani <> wrote:
    > mike b wrote:
    > > On Oct 16, 3:45 pm, Gianni Mariani <> wrote:
    > >> mike b wrote:

    >
    > >>> Sincere thanks to everyone who responded, the problem has been
    > >>> solved. The issue it seems is that I was defining my member
    > >>> specializations in the header but only a declaration for the
    > >>> specialization is allowed in the header, the actual implementation
    > >>> must go in the implementation file, .cpp.
    > >> Sounds strange. What errors were you getting ?

    >
    > > I was getting errors about my specialization being defined multiple
    > > times. This was with GCC 4.

    >
    > Declare the template as "inline" as see if you get the same errors.


    An explicit function specialization follows the same rules as any
    other C++ function: in order to be defined in a header file, the
    specialization must be declared "inline."

    Greg
     
    Greg Herlihy, Oct 17, 2007
    #15
    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. Johan Nilsson
    Replies:
    5
    Views:
    2,555
    Victor Bazarov
    Jun 25, 2003
  2. Dave
    Replies:
    4
    Views:
    7,677
    pdixtl
    Jun 4, 2010
  3. Ruben Campos
    Replies:
    3
    Views:
    6,473
  4. Joseph Turian
    Replies:
    4
    Views:
    597
    John Carson
    Mar 20, 2006
  5. dolphin
    Replies:
    3
    Views:
    1,349
    Pete Becker
    Dec 5, 2007
Loading...

Share This Page