如何在C++模板中实现Java Generics自限类型的等价物

Dav*_*les 0 c++ java generics templates

我在Java中有一小部分算法用于播放多个回合制游戏,例如TicTacToe,Othello,Checkers等.我使用Java Generics(自我绑定类型)来使用相同的算法而不必为每场比赛专门改变它们.我在这里没有显示使用自绑定类型的原因,但是评估函数需要它.

public interface Game<GAME extends Game<GAME>> {
    GAME copy();
    int getCurPlayer();
    ...
}

public class TicTacToe implements Game<TicTacToe> {
    ...
    @Override
    public TicTacToe copy() {
        ...
    }
    @Override
    public int getCurPlayer() {
        ...
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

今天,为了学习,我尝试使用C++模板将我的Java代码移动到C++.

这是我的方法,显然它没有用.

Game.h

template <typename T>
class Game
{
    public:
        virtual T copy() const = 0;
        virtual int cur_player() const = 0;
        ...
};
Run Code Online (Sandbox Code Playgroud)

TicTacToe.h

class TicTacToe : public Game<TicTacToe>
{
public:
    virtual TicTacToe copy() const;
    virtual int cur_player() const;
    ...
};
Run Code Online (Sandbox Code Playgroud)

TicTacToe.cpp

TicTacToe TicTacToe::copy() {
    ...
}

int TicTacToe::cur_player() {
    ...
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译时,我得到的错误是:

out-of-line definition of 'copy' does not match any declaration in 'TicTacToe'

out-of-line definition of 'cur_player' does not match any declaration in 'TicTacToe'
Run Code Online (Sandbox Code Playgroud)

...对于其他每个纯虚函数都是一样的.

Pup*_*ppy 5

您的定义也需要const适用于它们.CRTP,在C++(奇怪的重复模板模式)中已知是完全有效的C++.

但是,这里没有必要virtual,CRTP用于静态调度功能并自动实现功能.

template <typename T>
class Game
{
    T& crtp_cast() { return *static_cast<T*>(this); }
    const T& crtp_cast() const { return *static_cast<const T*>(this); }
public:
    T copy() const { return crtp_cast(); }
    int cur_player() const { return crtp_cast().cur_player(); }
    ...
};
Run Code Online (Sandbox Code Playgroud)

注意,在这种情况下,派生类并没有需要执行"复制"功能,拷贝构造函数都会被自动"复制"来调用.但是,在一般情况下,由于模板是鸭子类型,所以不必做这种事情,通常你只需使用标准模板.与Java的Generics不同,C++的模板与继承无关 - 您可以实例化的类型不必从公共接口继承.

template<typename Game> void f(const Game& g) {
    std::cout << g.cur_player();
}
class X {
public:
    int cur_player() const { return 1; }
};
class Y {
public:
    int cur_player() const { return 2; }
};
int main() {
    f(X());
    f(Y());
}
Run Code Online (Sandbox Code Playgroud)