Reputation: 221
I would like to mimic the following behavior using CRTP:
#include <vector>
#include <memory>
class GameNumber {
public:
~GameNumber(){}
};
class GameNumber_real : public GameNumber {
public:
GameNumber_real (float m) {n = m;}
~GameNumber_real(){}
private:
float n;
};
class GameNumber_sets : public GameNumber {
public:
GameNumber_sets (float n, float m) {
left.push_back (std::make_shared<GameNumber_real>
(GameNumber_real(n)));
right.push_back (std::make_shared<GameNumber_real>
(GameNumber_real(m)));
}
~GameNumber_sets(){}
private:
std::vector <std::shared_ptr<GameNumber>> left;
std::vector <std::shared_ptr<GameNumber>> right;
};
My attempt was:
template <class T>
class GameNumber {}
class GameNumber_real : public GameNumber<GameNumber_real> {
public:
GameNumber_real (float m) {n = m;}
private:
float n;
};
class GameNumber_sets : public GameNumber<GameNumber_sets> {
public:
GameNumber_sets (float n, float m) {
left.push_back (std::make_shared<GameNumber_real>
(GameNumber_real(n)));
right.push_back (std::make_shared<GameNumber_real>
(GameNumber_real(m)));
}
private:
std::vector <std::shared_ptr<GameNumber>> left;
std::vector <std::shared_ptr<GameNumber>> right;
};
The compiler error is:
include/game_number.hpp:44:33: error: no matching function for call to
‘std::vector<std::shared_ptr<GameNumber<GameNumber_sets>>>
::push_back(std::shared_ptr<GameNumber_real>)’
(GameNumber_real(n)));
From the message I understand that inside GameNumber_sets, GameNumber resolves to GameNumber_GameNumber_sets_. I would be really glad if you could tell me how achieve the behavior I expected.
Upvotes: 1
Views: 243
Reputation: 181
You can explicitly specify template argument like GameNumber<GameNumber_real>
and it will solve your problem.
Also you can pass constructor arguments directly to std::make_shared
.
Improved code:
template <class T>
class GameNumber {};
class GameNumber_real : public GameNumber<GameNumber_real> {
public:
GameNumber_real (float m) {n = m;}
private:
float n;
};
class GameNumber_sets : public GameNumber<GameNumber_sets> {
public:
GameNumber_sets (float n, float m) {
left.push_back (std::make_shared<GameNumber_real>(n));
right.push_back (std::make_shared<GameNumber_real>(m));
}
private:
std::vector <std::shared_ptr<GameNumber<GameNumber_real>>> left;
std::vector <std::shared_ptr<GameNumber<GameNumber_real>>> right;
};
However I don't understand why do you need CRTP in here, there is no use of it in your example.
Edit:
As far as I know you can't use CRTP as interface. However there is std::any
(https://en.cppreference.com/w/cpp/utility/any) which may help if c++17 is ok for you.
Code would look like:
template <class T>
class GameNumber {};
class GameNumber_real : public GameNumber<GameNumber_real> {
public:
GameNumber_real (float m) {n = m;}
private:
float n;
};
class GameNumber_sets : public GameNumber<GameNumber_sets> {
public:
GameNumber_sets (float n, float m) {
left.push_back (std::make_shared<std::any>
(GameNumber_real(n)));
right.push_back (std::make_shared<std::any>
(GameNumber_real(m)));
}
private:
std::vector <std::shared_ptr<std::any>> left;
std::vector <std::shared_ptr<std::any>> right;
};
Upvotes: 1