Link to home
Start Free TrialLog in
Avatar of havman56
havman56

asked on

Nested class linker error

template<class T>
class  ctemplate
{
      public:
       void foo();
      private:
            class Nested
            {
            public:
                  A(){}
                  ~A(){}
                  static void test();
            };
};

void ctemplate<T>::foo()
{
 
Nested :: test(); // this line gives linker error
}


void ctemplate<T>::Nested::test()
{
}

I am getting unresolved external symbol  in linker error in MSC vc 6.0

even if have statement

template<T>
void ctemplate<T>::Nested::test();

i am getting the same error.

kindly help me .....


ASKER CERTIFIED SOLUTION
Avatar of tinchos
tinchos

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of efn
efn

You have to define the functions as templates:

template <class T>
void ctemplate<T>::foo()
{
      Nested :: test(); // this line gives linker error
}


template <class T>
void ctemplate<T>::Nested::test()
{
}

The definitions don't have to be inside the class declaration, but the compiler does have to see them when it compiles code that instantiates the template--template function definitions can't be separately compiled with this compiler.  So normally either the definitions are in the header file or they are in a .cpp file that the header file #includes at the end.

--efn
main way to do template definition if you don't want to clutter up your declaration ...

template<class T>
class A
{
public:
  A();
};

template<class T>
A::A()
{
}

otherwise you have to put a
#include <a.cpp> at the bottom of your a.h file ... and frankly that is way too misleading for my taste so I either put the definition in the class declaration, or I define the methods after the declaration in the same .h file.
Avatar of havman56

ASKER


hi efn,

sorry , it is my mistake of not  specifiing template <class T> before fucntion foo() when posting it.anyway it should gives compilation error for not specifiing it.

But in my real code i have template<class T> before function it compiles well.
linker error happens.

so the problem is still there..

for nested class what ever u said wont work....implementation later than declaration

cant we use the implementation in later when  nested class used with templates ?????

Tinchos,
yes i knew u can have it as u said implementation during declaration it self.

but my problem is i need to have implementation seperate.
so MSC doesnt support ?




Sincerely I'm not sure

I do know that I had some problems with it and that I solved them placing all implementations inside the class declaration, but I cannot assure neither that it does support it nor it does not support it

Sorry

Tincho
How is your code packaged in files?

If you are trying to compile template function implementations separately and link them, that won't work.

When I put code as in your question in a single cpp file, it compiles and links just fine with VC++ 6.

--efn
hi tinchos,

Thanks for ur help!

efn

see my code it gives linker error unresolved external symbol i have everything in same .cpp file!!!

template<class T>
class  ctemplate
{
     public:
      void foo();
     private:
          class Nested
          {
          public:
               Nested(){}
               ~Nested(){}
               static void test();
          };
};

template <class T>
void ctemplate<T>::foo()
{
 
Nested :: test(); // this line gives linker error
}


template<class T>
void ctemplate<T>::Nested::test()
{
}


main()
{
      ctemplate<char> obj;
      obj.foo();
}

please help me !!!!

havman
It looks like this is a known compiler bug and Tincho has given you the workaround.

See:

http://support.microsoft.com/default.aspx?scid=kb;EN-US;128789

--efn
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Accept: tinchos {http:#10079535}

Please leave any comments here within the next four days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
No one had given any correct solution ot the problem i had.
i feel still this question can be open.

for next 1 month. If i didnt get suitable comments for my problem then . i want to revoke the points.

i dont wnat to give points to anyone bcoz no one really helped me out !

Please explain what is wrong with the solution we have given you.

In the very first comment, Tincho wrote "Sincerely I dont believe that MSVC 6.0 allows to have the implementation of a template out of its declaration.  So I would try placing all of it inside the class declaration."

In my last comment, I concluded that this solution was necessary due to a known compiler bug.  The last code you posted does not implement this solution.  Our advice is to locate the implementation of the nested class member function inside the nested class declaration.  Just having it in the same file is not enough.

The following code implements this solution.  It compiles and links without error in Microsoft Visual C++ 6.0.

template<class T>
class  ctemplate
{
     public:
      void foo();
     private:
          class Nested
          {
          public:
               Nested(){}
               ~Nested(){}
               static void test() {}
          };
};

template <class T>
void ctemplate<T>::foo()
{
 
Nested :: test(); // this line does not give linker error
}

int main()
{
     ctemplate<char> obj;
     obj.foo();
       return 0;
}

--efn
havman56,

I'm not sure if you're still looking for a solution/better understanding but here it is.

The problem:
The compiler sees that you instantiate an object of type ctemplate<char> and generates code for that class using the template you supplied.  Here is where the bug occurs.  Code is not generated for the static function of the nested template class even though your implementation is correct:

template<class T>
void ctemplate<T>::Nested::test() {}

This is a bug in VC++6.  Now ctemplate<char>::Nested::test() remains an unresolved symbol left for the linker to resolve.  The linker goes to do it's thing and looks for ctemplate<char>::Nested::test(). It too will obviously not find it since the compiler never generated code for it.  Hence the linkage error.

The solution:
Static nested class template member functions in VC++6 must unfortunately either be inline (Method #1) to ensure that the compiler won't 'forget' to generate the code;  or generate the code yourself, that is, implement the function specifically for each type that will be used (Method #2).

template<class T>
class  ctemplate {
public:
    void foo();
private:
    class Nested {
    public:
        Nested(){}
        ~Nested(){}
        static void test1() {/*your code */}; // Workaround method #1
        static void test2();
    };
};

template <class T>
void ctemplate<T>::foo() {
    Nested::test1(); // this is calling ctemplate<T>::Nested::test1()
    Nested::test2(); // this is calling ctemplate<T>::Nested::test2()
}

// Workaround method #2
void ctemplate<char>::Nested::test2() {/*your code */}

int main() {
    ctemplate<char> obj;
    obj.foo();
    return 0;
}

>> but my problem is i need to have implementation seperate.
>> so MSC doesnt support ?

Method #2 would be your only option with VC++6.  You would have to have a implementation for each type. ie:

void ctemplate<char>::Nested::test2() {/*your code */}
void ctemplate<int>::Nested::test2() {/*your code */}
void ctemplate<double>::Nested::test2() {/*your code */}
    ....
    ....

b.