I have a template class:
template<typename A, typename B>
class A {
};
In another .h file
template<typename A, typename B>
class A; //forward declaration
How could I declare m_A
over here? I keep getting C++ forbids declaration 开发者_StackOverflowof A
with no type error:
class B {
A* m_A;
};
If you don't know the types that you want to instantiate A
with when inside of B
, then you will have to also make a template out of B
template<typename A1, typename B1>
class B
{
A<A1, B1>* m_A;
};
Either that, or you would have to instantiate A
as a specific type, i.e.,
class B
{
A<Type_1, Type_2>* m_A;
};
Declare m_A
with some specific types for A
:
class B
{
A<int, char>* m_A;
}
If you B is such that you don't know a priori what types should be used in the m_A
declaration, perhaps B
needs to be template class and you'd use those type parameters in the declarion of m_A
.
Templates are nice little peculiar beasts. The template definition must be available for the compiler at the place of instantiation, so the most common pattern is defining the template in the header so that each translation unit that uses the templated methods (and thus instantiates them) will have access to the definition.
Alternatively, you can provide the template definitions in a single translation unit, but you will have to ensure that you are instantiating the template for all the types for which you use it in the whole program.
// header
template <typename T> struct A
{
void foo( T );
}
// single translation unit
#include "header"
template <typename T> // template member definitino
void A<T>::foo( T x ) {
std::cout << "A(" << x << ")" << std::endl;
}
template struct A<int>; // explicit instantiation for int
template struct A<double>; // explicit instantiation for double
// main
#include "header"
int main() {
A<int> ai;
ai.foo( 5.5 ); // will print 5 (int rounded down)
A<double> ad;
ad.foo( 5.5 ); // will print 5.5
A<char> ac;
ac.foo( 'a' ); // linker error, A<char>::foo undefined
}
Because in general templates are meant to be used with any type through the program, defining the template methods in a single translation unit and using explicit instantiation is not a good idea. On the other hand, in the few cases where you need to control the set of types for which the template is instantiated, or under a few other circumstances (reducing large compile times [*]) you might want to follow this second approach. But again, in the general case, it is simpler to define the member functions in the header, and again it is simpler to defined them inside the class definition.
[*] Templates are compiled in all translation units in which they are used, which means that if you instantiate A<int>::foo
in 5 different translation units, the compiler will compile it 5 times, and then the linker will discard 4 of the instantiations. In some cases where the template is complex, it might be an advantage to compile it once in one translation unit and just call it from the others. Note that with explicit instantiation, all member functions are compiled, while with implicit instantiation (at the place of use) only those members that are actually used will get compiled, so depending on the situation, explicit instantiation may be more costly than implicit instantiation (in classes with many members)
template<typename A> void B<A>::function() { }
Btw, do not separate definitions and declarations while writing a template class.
EDIT: changed < to < and > to > Before that code looked like:
template void B::function() { }
精彩评论