c++ call template constructor to instantiate

236 views Asked by At

Give the following program,

hello.h

#ifndef HELLO_
#define HELLO_

template <typename T>
class hello
{
  T _data;
public:
  hello(T t)
  : _data(t) {}
};

template <typename T>
class world : public hello<T>
{
  T _data;
public:
  world(T t)
  : hello<T>(t) {}
};

#endif

main.cc

#include <iostream>
#include "hello.h"

using namespace std;

class Foo
{
  int _x;
public:
  Foo(int x) : _x(x) {}
};

int main()
{
  Foo f(1);
  world<Foo> w(f);

  return 0;
}

I compiled it with c++11 and the compiler gives the following error messages:

In file included from main.cc:2:0:
hello.h: In instantiation of ‘world<T>::world(T) [with T = Foo]’:
main.cc:16:22:   required from here
hello.h:19:15: error: no matching function for call to ‘Foo::Foo()’
   : hello<T>(t) {}
               ^
main.cc:10:3: note: candidate: Foo::Foo(int)
   Foo(int x) : _x(x) {}
   ^
main.cc:10:3: note:   candidate expects 1 argument, 0 provided
main.cc:6:7: note: candidate: constexpr Foo::Foo(const Foo&)
 class Foo
       ^
main.cc:6:7: note:   candidate expects 1 argument, 0 provided
main.cc:6:7: note: candidate: constexpr Foo::Foo(Foo&&)
main.cc:6:7: note:   candidate expects 1 argument, 0 provided

There must be something I missed in the template definition, but I am not sure where it is. For primitive types such as int or double, it works. It does not work with class I defined, e.g. Foo.

2

There are 2 answers

0
Danh On BEST ANSWER

In world<T>

template <typename T>
class world : public hello<T>
{
  T _data;
public:
  world(T t)
  : hello<T>(t) {}
};

Because T in this case (Foo) is not default-constructible. I guess this is mistaken added because there is another T _data; in hello<T>. Remove it, and your code should work well. Like this:

template <typename T>
class world : public hello<T>
{
public:
  world(T t)
  : hello<T>(t) {}
};

Demo


Not related to the error you asked, in your main:

world<Foo> w();

This declares w as a function with no parameters and return world<Foo>.

I guess it's not what you want (forgive me if I were wrong). I guess this is what you want:

world<Foo> w(f);

or

world<Foo> w{f};
0
4af2e9eb6 On

Private data from the parent class are encapsulated and they do exist. Repeatedly define the data with the same variable name in the children class would incur such error, regardless it's about template class or just normal class.