Rick
Rick

Reputation: 451

Is it possible to create a template instance with a non-default constructor in c++?

Is it possible to specify which constructor to use when inheriting from a template based class? It seems like a basic thing, but I can't seem to figure out how to accomplish this in C++...

In the following code, I want to use a non-default constructor for the PlayerStats object when I create a PlayerActor (which inherits from the BaseActor template class).

class BaseStats {
public:
   BaseStats ()
   {

   }

private:
};

class MonsterStats : public BaseStats {
public:
   MonsterStats()
   {

   }

private:
};

class PlayerStats : public BaseStats {
public:
   PlayerStats(
      const bool is_new) : 
         m_is_new(is_new)
   {

   }

private:
   const bool m_is_new;
   PlayerStats(); //Don't want this being used...
};

template <class ActorStatsClass>
class BaseActor
{
public:
   BaseActor()
   {

   }

private:
   ActorStatsClass m_stats;
};

class MonsterActor: public BaseActor<MonsterStats> {
public:
   MonsterActor()
   {

   }
private:
};

// This is where I'm not sure how to tell the template to use a non-default constructor...
// I get an error saying "PlayerStats::PlayerStats": cannot access private member declared in "PlayerStats". (Which is intended, but I don't want it to try and use the default constructor...)
class PlayerActor : public BaseActor<PlayerStats> {
public:
   PlayerActor(const bool is_new)
   {

   }
private:
   PlayerActor(); // Don't use this...
};

Upvotes: 3

Views: 174

Answers (2)

Mooing Duck
Mooing Duck

Reputation: 66942

template <class ActorStatsClass>
class BaseActor
{
public:
   BaseActor()
   {

   }

private:
   ActorStatsClass m_stats;
};

If this BaseActor class is going to have arbitrary members, it needs ways to construct those arbitrary members. So it needs a generic constructor.

template <class ActorStatsClass>
class BaseActor
{
public:
   template<class...Us>
   BaseActor(Us&&...vs)
   : m_stats(std::forward<Us>(vs)...)
   { }

private:
   ActorStatsClass m_stats;
};

This uses forwarding, that whatever parameters are passed to BaseActor, it just passes them directly to constructing the m_stats member.

This allows:

class PlayerActor : public BaseActor<PlayerStats> {
public:
   PlayerActor(const bool is_new)
   : BaseActor<PlayerStats>(is_new)
   { }
   PlayerActor() = delete; // Note: this is better than making it private
};

Upvotes: 5

just a guy
just a guy

Reputation: 137

your template only says which type to use you need to define which constructor to use with the object itself. for example:

template <class ActorStatsClass>
class BaseActor
{
public:
   BaseActor():m_stats(arguments)//call a constructor of m_stats when creating an instance of this class
   {

   }

private:
   ActorStatsClass m_stats;
};

Upvotes: 1

Related Questions