views:

113

answers:

5

In the file test.cpp, I have this:

template <typename T>
class A
{
public:
  A(int a){};
  virtual ~A();

private:
};

class B : public A<int>
{
public:
  B(int a):A(a){};
  virtual ~B();

private:
};

int main()
{
  return 0;
}

When I compile it, I get this:

jason@jason-linux:~/Documents/ECLibrary$ g++ -g -Wall -Wextra -pedantic-errors test.cpp -o tdriver
test.cpp: In constructor ‘B::B(int)’:
test.cpp:14: error: class ‘B’ does not have any field named ‘A’
test.cpp:14: error: no matching function for call to ‘A<int>::A()’
test.cpp:5: note: candidates are: A<T>::A(int) [with T = int]
test.cpp:3: note:                 A<int>::A(const A<int>&)

I do not want a default constructor for my base class, since it doesn't make sense in my code. I just want my derived class to perform the called constructor of the base class and do some extra construction for the extra stuff in the derived class. I'm really not sure why it is trying to call the default constructor of the base class when I'm trying to explicitly call an alternate constructor. Am I missing something here?

Thanks

+8  A: 

You can add the template argument list to A:

B(int a) : A<int>(a) { } 

Note that the code that you have--using A without the template argument list--is valid C++. Comeau and Visual C++ 2010 both accept the code as-is.

g++ 4.3 does not accept the code without the template argument list. Perhaps someone can test a later version of g++ or check the g++ bug database to see whether it is a known issue (I don't regularly use g++ and am not familiar with their bug database).

James McNellis
As does MSVC...
Oli Charlesworth
@Oli: Good to know. Perhaps someone here can test with a later version of g++ and/or check the g++ bug database. I'm afraid I don't use g++ regularly enough to be familiar with it.
James McNellis
Thanks, it worked. I'm so rusty with C++.
Jason Iverson
@James, @Oli: OK, correct me if I am wrong, but I think that injected class names apply only if the class is a template, or if the base is dependent. So maybe this isn't a g++ bug after all? I may be completely wrong though...
Armen Tsirunyan
@Armen: No, the injected class name can be used "whenever it is in scope" (C++03 14.6.1/2a, which also gives an example of using it in a derived class)
James McNellis
+3  A: 

Try B(int a):A<int>(a){} instead.

Oli Charlesworth
A: 

Needs to read:

class B : public A<int>
{
public:
  B(int a):A<int>(a){};
  virtual ~B();

private:
};

and it will work just fine.

Omnifarious
A: 

You are trying to initialize your base class as A, but you don't derive from A, you derive from A<int>

TokenMacGuy
The injected class name for a template can be used with or without the template argument list, so as long as `A` is unambiguous, you can use `A` and `A<int>` interchangeably (if you derived from two specializations of `A`, as in `class B : A<int>, A<float> { };`, then `A` would be ambiguous inside of `B` and you would have to use `A<int>` and `A<float>`, respectively).
James McNellis
A: 

I guess you're trying to do explicit specialization of class A for integer. Guess should be written as template<> Class A<int>...

Samrat Patil