3

I am trying to compile an example from "Design Patterns" and I am facing the following problem:

I have a base class MapSite:

class MapSite{
public:
    MapSite();
    virtual ~MapSite(); 
    virtual void Enter() = 0;
};

and a derived class Room:

class Room : public MapSite final{

private:
    unsigned int room_number;

public:
    Room(unsigned int rn) : room_number(rn) {};

    virtual void Enter() override;
};

From another class I want to call the function

virtual std::unique_ptr<Room> MakeRoom(unsigned int n) {return make_unique<Room(n)>();} 

When I do so I get the following error:

error: temporary of non-literal type ‘Room’ in a constant expression
  virtual std::unique_ptr<Room> MakeRoom(unsigned int n) {return unique::make_unique<Room(n)>();}

So I thought the problem may be that the constructor has to be constexpr in order to call the constructor of Room from another function, but setting the constructor to:

constexpr Room(unsigned int rn) : room_number(rn) {};

will produce this error:

error: call to non-constexpr function ‘MapSite::MapSite()’
  constexpr Room(unsigned int rn) : room_number(rn) {};

My basic question is whether I can make a derived class constructor constexpr, even if the base class constructor is not. Or maybe if there is a much better concept to solve this problem.

PS: make_unique is a c++14 feature which I emulated from here How to implement make_unique function in C++11? for c++11, which I am compiling with

Ajay
  • 18,086
  • 12
  • 59
  • 105
Gartmair
  • 383
  • 1
  • 3
  • 9
  • Ask yourself: what is it about that code that is even trying to use `Room` in a constant expression and why? – Barry May 30 '17 at 15:49

2 Answers2

10

The issue here is not that Room needs a constexpr constructor but you are passing a value to a template that expects a type. in

virtual std::unique_ptr<Room> MakeRoom(unsigned int n) {return make_unique<Room(n)>();} 

the Room(n) part tries to construct a Room and use it as a template parameter for make_unique. This is not what you want to do. make_unique expects a type as it constructs a std::unique_ptr of that type from the parameters you pass to it. If you want to construct a Room with n then you use

virtual std::unique_ptr<Room> MakeRoom(unsigned int n) {return make_unique<Room>(n);} 
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
9

Can i make the constructor of a derived class contexpr if the base class constructor is not constexpr?

No, you can not.

A constexpr function can not call non-constexpr functions. A constructor must call all sub-object (including the base-subobjects) constructors. Therefore all sub-object constructors must be constexpr or else the complete object constructor may not be constexpr.

That said, your original problem is separate, and is covered by NathanOliver's answer.

eerorika
  • 232,697
  • 12
  • 197
  • 326