Reputation: 507
I had a class that worked fine. I wanted to change it to a template class. Suppose I have now:
template <MyTypes::smallType T = Mytypes::myInt>
class A{....}
Now assume that the class A is used in many other hpp and cpp files, sometimes by including the header file and sometimes by forward declaration as:
template <MyTypes::smallType T> class A;
And it is mostly used as std::shared_ptr<A<>>
in other classes and function calls.
Now assume that I have another class B which is very similar to A, but used in fewer places (still in other cpp files through forward declaration), and not in a shared_ptr.
template <MyTypes::smallType T = Mytypes::myInt>
class B{....}
When trying to compile, I get the error "too few template arguments" for A<>
, but not for B<>
. The project is very large and I do not have a guess in order to produce a simple example with the same problem. Could you help me (even by gusses), what might be causing the problem? Can it be shared_ptr? Can it be some typedefs in the form of typedef std::shared_ptr<A<>> APtr
? I also get the error "unspecialized class template or generic can't be used as a template or generic argument for template or generic parameter 'param', expected a real type" if that can help with guesses.
I would appreciate your help.
Upvotes: 2
Views: 12036
Reputation: 10021
Quite simply, the forward declaration needs the default parameters. Simply look at it this way, in simplified form:
template<class T> A;
std::shared_ptr<A<>> a;
When the compiler sees this, that is all the information it has. So, in this case, A<>
is obviously missing a type for its template parameters. Now, if you do:
template<class T = int> A;
std::shared_ptr<A<>> a;
Then the compiler can deduce that A<>
is really A<int>
.
Here's the problem with that though. From [temp.param]/12
A template-parameter shall not be given default arguments by two different declarations in the same scope.
[ Example: template<class T = int> class X; template<class T = int> class X { /* ... */ }; // error —end example ]
So, if you use a default parameter on your forward declaration, you can't use it on the template itself. Fun times.
A cheat to get around this is to have an extra header file which contains just the forward declaration of the template with default params, and all files using the template include that, instead of the full definition of the template (until the full definition is required), including the template's definition. The template definition would not need the default parameters. Not very fun, but it would work.
Alternatively, don't forward declare.
Upvotes: 3