Link to home
Start Free TrialLog in
Avatar of Zulma9999
Zulma9999

asked on

Correct template class forward declaration

I know there's a method for doing forward declaration for template classes in the cpp file, but I don't remember what was the correct method.

template<class T>
class foo
{
public:
T x;
};

How do I get a forward declaration of the above template for foo<int>??=9673F
Avatar of thienpnguyen
thienpnguyen


// forward declare
template<class T>
class foo;


template<class T>
class bar
{
public:
     T x;
     foo<int> *f;
};

template<class T>
class foo
{
public:
     T x;
     bar<T> *b;
};

Avatar of Zulma9999

ASKER

I'm sorry thienpnguyen, but that's not what I'm talking about.

Let me be more specific.

//I have this in foo.h file
template<class T>
class foo
{
public:
 T FunctionXYZ(T xyz);
T x;
};

//I have this in the foo.cpp file
template<class T>
T foo::FunctionXYZ(T xyz)
{
 return xyz + xyz;
}


With the above coode, how would I do a forward declaration of foo<int> inside the foo.cpp file.
There's a forward declaration method that allows you to use foo<int> in another cpp file when you have the template function code in the cpp file instead of the header file.
I'm looking for that method.
when you  implement template, you have to put
"class's declare and  class's implement" in same
header file. You can not have separate to header .h
and .cpp . Look at some stl template source code,
you will see that point.
>> when you  implement template, you have to put
>> "class's declare and  class's implement" in same
>> header file.

That is not true.  You can use the export keyword to define a exported  template.  From the C++ standard 14.7

An  exported  template
  need  only  be declared (and not necessarily defined) in a translation
  unit in which it is instantiated.  A template function  declared  both
  exported and inline is just inline and not exported.


For example

//I have this in foo.h file
export template<class T>  // NOTE "export".
class foo
{
   public:
   T FunctionXYZ(T xyz);
   T x;
};

//I have this in the foo.cpp file
template<class T>
T foo::FunctionXYZ(T xyz)
{
   return xyz + xyz;
}

HOWEVER, making this work (for the compiler) is not an easy thing, so not all compilers currretly support it.  howevr it is part of the offical C++ standard langauge.
Sorry, but this is not what I'm looking for.
I'm looking for a method that will work with Visual C++.
Your method will not work with VC++
Avatar of Axter
Try modifying your code to the following:

//I have this in the foo.cpp file
template<class T>
T foo<T>::FunctionXYZ(T xyz)
{
  return xyz + xyz;
}

>> I'm looking for a method that will work with Visual C++.
>> Your method will not work with VC++
You never mentioned that in your question.   How were we to know that.

The method I showed you is 100% legal C++  It is the only way to do it.

You asked

"I know there's a method for doing forward declaration"

What i showed you is THE method.  There is no other method.  That method is completely legal C++.  The fact that you are using a compiler that doesn't yet support it is out of our control--especially if you don't tell us that.
I didn't know that the compiler was going to be an issue, or I would have provided that information.

>>That method is completely legal C++.
I don't care if it's legal.  If I can't use it then it's worthless to me.

If you can't provide me with a work solution, then I'll wait for some other expert to help me.
Axter,
I tried your method, and it does let me compile the code, but it fails when linking.
I get this error

error LNK2001: unresolved external symbol "public: int __thiscall foo<int>::FunctionXYZ(int)" (?FunctionXYZ@?$foo@H@@QAEHH@Z)

Any ideas?
thienpnguyen,
>> when you  implement template, you have to put
>> "class's declare and  class's implement" in same
>> header file.

I know that there is a way to do this by putting a specific declaration in the cpp file of the template.  The declaration is specific to the class used for T
ASKER CERTIFIED SOLUTION
Avatar of Axter
Axter
Flag of United States of America image

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
>> If you can't provide me with a work solution, then I'll wait for some other expert to help me.
You will wait forever.  This is the only way to do it and it is not jey supported by VC.

>>  it fails when linking.I get this error
This will be a problem.

Vc does not support exported templates.  All the tempalte code that Vc generates will have internal linkage.  There is no way to tel the VC compiler to generate template code with external linkage.  So there is no way for tempalte code in one translation unit to satisfy imported tempalte code from another translation unit.

I'm not making this up or anything.  I told you about this at the start when I said

>>  not all compilers currretly support
>> it.  howevr it is part of the offical C++ standard langauge.

>> I know that there is a way to do this by putting a specific declaration in the cpp file
YES,.   I told you what this is.  but VC doesn't support it.

You know that it can be done.  You don't know that VC supports it right?  Well it doesn't.  There are MS knowlegebase articles about the fact that it doesn't support it.
From the MS knowledgebase
********************************************************************
PRB: LNK2001 on Template Member Functions

--------------------------------------------------------------------------------
The information in this article applies to:

Microsoft Visual C++, 32-bit Enterprise Edition, versions 5.0, 6.0
Microsoft Visual C++, 32-bit Professional Edition, versions 5.0, 6.0
Microsoft Visual C++, 32-bit Learning Edition, version 6.0

--------------------------------------------------------------------------------


SYMPTOMS
You receive a LNK2001 error message on template member functions unless the member functions are also defined in the same translation unit.



CAUSE
The compiler does not support the use of the "export" keyword as specified in the C++ standard below:

Section 14
Para# 7: Declaring a class template exported is equivalent to declaring all of its non-inline function members, static data members, member classes, member class templates and non-inline function member templates which are defined in that translation unit exported.

Para# 8: Templates defined in an unnamed namespace shall not be exported. A template shall be exported only once in a program. An implementation is not required to diagnose a violation of this rule. A non-exported template that is neither explicitly specialized nor explicitly instantiated must be defined in every translation unit in which it is implicitly instantiated (temp.inst) or explicitly instantiated (temp.explicit); no diagnostic is required. An exported template need only be declared (and not necessarily defined) in a translation unit in which it is instantiated. A template function declared both exported and inline is just inline and not exported.



RESOLUTION
You have the following two options:

Keep the template declaration and definition together in one translation unit.


If you know in advance how your template class will be used in your application, you can perform explicit instantiation for the template class.

For example, for class MyStack declared in Myprog.h
template <class T> MyStack;
and implemented in Myprog.cpp, the following explicitly instantiates MyStack for int variables:
template class MyStack<int>;






MORE INFORMATION
Explicit instantiation allows you to create an instantiation of a template class or function without actually using it in your code. The idea is to explicitly instantiate all possible types for the template class in the implementation file. Thus, when the .cpp file is compiled, the code is generated for these instantiations, alleviating the LNK2001 error.

Please refer to the Visual C++ Help for more information regarding explicit instantiation.



REFERENCES
For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

Q128789 BUG: LNK2001 on Member Function When Use Nested Class Template

Additional query words:

Keywords : kbLangCPP kbLinker kbVC kbVC500 kbVC600 kbDSupport
Issue type : kbprb
Technology : kbVCsearch kbAudDeveloper kbVC32bitSearch kbVCPE500 kbVCPE600 kbVCEE500 kbVCEE600 kbVCLE600
 


Last Reviewed: May 5, 2001
? 2001 Microsoft Corporation. All rights reserved. Terms of Use.
 

Axter,
I just tried it out, and it works.
I knew it could be done.  I just couldn't remember how.

I was starting to believe the other expert.

Thanks a lot.  You're a lifesaver.
nietod,
If you haven't read Axter's comment, you can do this in VC++ by doing this "template foo<int>"

Thanks for trying anyway.
FYI Zulma9999,
You do realize that the method I posted requires you to make this type of declaration for each type you use the foo class with.

>> f you haven't read Axter's comment, you can do this in VC++ by doing this "template foo<int>"
And that then works for all template instanciations?    Nope.

Now try instiation your class for type char.  it doesn't work.

Read the knowledgabe article I posted.  it suggests this as a workaroud, but only for the case where you know in advance exaclly what template parameters the class will be instanciated for.   You don't know that.  Or if you do know that, it was not presented in your question.
>>You do realize that the method I posted requires you to
>>make this type of declaration for each type you use the
>>foo class with.
Yes, I know this already.  I have my reasons for wanting the function code in the cpp file only.  And it is worth the extra maintenance required to update the file for every new type I want to use.

>>And that then works for all template instanciations?    
>>Nope.
This will work for all templates.

>>Now try instiation your class for type char.  it doesn't
>>work.
I just tried it with char, and it works.  I'm not sure what you're trying to get at.