首页 > 解决方案 > CRTP如何使派生类具有基类的容器

问题描述

我想使用 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;
};

我的尝试是:

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

编译器错误是:

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)));

从消息中我了解到,在 GameNumber_sets 中,GameNumber 解析为 GameNumber_GameNumber_sets_。如果您能告诉我如何实现我所期望的行为,我将非常高兴。

标签: c++template-meta-programmingcrtp

解决方案


您可以显式指定模板参数GameNumber<GameNumber_real>,它将解决您的问题。

您也可以将构造函数参数直接传递给std::make_shared.

改进的代码:

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

但是我不明白为什么在这里需要 CRTP,在您的示例中没有使用它。

编辑:

据我所知,您不能使用 CRTP 作为接口。但是,如果 c++17 适合您,那么有std::anyhttps://en.cppreference.com/w/cpp/utility/any )可能会有所帮助。

代码如下所示:

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

推荐阅读