Linker error with templates

This is a discussion on Linker error with templates within the C++ Programming forums, part of the General Programming Boards category; I'm having a problem with the following scheme. If everything is in one source file, it compiles and links fine: ...

  1. #1
    The larch
    Join Date
    May 2006
    Posts
    3,573

    Linker error with templates

    I'm having a problem with the following scheme. If everything is in one source file, it compiles and links fine:

    Code:
    #include <iostream>
    
    enum Type {TYPE_A, TYPE_B};
    
    class Test
    {
        public:
        template <Type N>
        void foo();
        
        void a();
        void b();
    };
    
    void Test::a()
    {
        std::cout << "A\n";
    }
    
    void Test::b()
    {
        std::cout << "B\n";
    }
    
    template <>
    void Test::foo<TYPE_A>()
    {
        a();
    }
    
    template <>
    void Test::foo<TYPE_B>()
    {
        b();
    }
    
    int main()
    {
        Test t;
        t.foo<TYPE_A>();
        t.foo<TYPE_B>();
        std::cin.get();
    }
    However, when I try to break this up into multiple files (as follows), I get multiple definition of Test::foo<>. What am I missing?

    Code:
    //type.h
    #ifndef TYPE_H
    #define TYPE_H
    
    enum Type {TYPE_A, TYPE_B};
    #endif
    
    //test.h
    #ifndef TEST_H
    #define TEST_H
    
    #include "type.h"
    
    class Test
    {
        public:
        template <Type N>
        void foo();
        
        void a();
        void b();
    };
    #include "foo.cpp"
    #endif
    
    //test.cpp
    #include "test.h"
    #include <iostream>
    
    void Test::a()
    {
        std::cout << "A\n";
    }
    
    void Test::b()
    {
        std::cout << "B\n";
    }
    
    //foo.cpp
    template <>
    void Test::foo<TYPE_A>()
    {
        a();
    }
    
    template <>
    void Test::foo<TYPE_B>()
    {
        b();
    }
    
    //main.cpp
    #include "test.h"
    #include "type.h"
    #include <iostream>
    int main()
    {
        Test t;
        t.foo<TYPE_A>();
        t.foo<TYPE_B>();
        std::cin.get();
    }
    (foo.cpp is not compiled separately.)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    >> template <Type N>
    Is that even proper syntax?

    It looks ok to me, but if that's not the actual code then there might be something else different.

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    This is actual code.

    template <Type N> is supposed to be a non-type template (Type is an enum) and I'm trying to create a specialization for each enum identifier.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Both main.cpp and test.cpp #include "test.h", which will #include "foo.cpp". So each has a copy?

    [edit]Don't #include "foo.cpp" from test.h and instead do this?
    Code:
    //main.cpp
    #include "test.h"
    #include "type.h"
    #include "foo.cpp"
    [edit=2]And sorry for my now deleted trigger-happy first reply if you saw it.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    For Narnia! Sentral's Avatar
    Join Date
    May 2005
    Location
    Narnia
    Posts
    719
    My only guess is that you could be splitting up a template declaration from it's implementation, which would confuse the linker. I don't think that's the problem though.
    Videogame Memories!
    A site dedicated to keeping videogame memories alive!

    http://www.videogamememories.com/
    Share your experiences with us now!

    "We will game forever!"

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Well, Dave's suggestion works but this seems to be going to give so much trouble that I'll just do with normal function parameters. I can't see now what kind of advantage I was hoping from templates.

    Thanks
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    All my experience with Templates & splitting them into .h & .cpp files so far leaves me with the simple conclusion: Don't do that!
    Template declaration & definition should be kept together in the .h file.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    The problem is that placing all the code that is currently in foo.cpp inside the test.h header will cause the same error, so placing it inside the header file doesn't help.

    I don't know what the problem is, but I expect it has something to do with template specializations for member functions. I know that there are extra restrictions on those.

    Actually, marking the functions as inline seems to solve the problem on VC++ 7.1.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Templates + ref to pointer + linker error.
    By Sparrowhawk in forum C++ Programming
    Replies: 8
    Last Post: 05-18-2009, 04:06 PM
  2. Linker errors with Templates...
    By Petike in forum C++ Programming
    Replies: 2
    Last Post: 09-03-2008, 09:52 AM
  3. Linker Errors with Templates
    By LPP in forum C++ Programming
    Replies: 16
    Last Post: 10-20-2006, 08:45 PM
  4. Questions about Templates
    By Shamino in forum C++ Programming
    Replies: 4
    Last Post: 12-17-2005, 11:22 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21