Search code examples
c++c++11templatesconstructorgeneric-programming

c++ call template constructor to instantiate


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.


Solution

  • 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};