C++ 模板,链接阶段未定义引用错误

C++ template, linking stage undefined reference error

提问人:fields1631 提问时间:8/21/2021 最后编辑:fields1631 更新时间:8/21/2021 访问量:281

问:

我正在使用 C++ 模板并遇到以下问题。

我尝试在类中使用类的方法,但是链接器报告错误。ImplGfuncImplM

user:/home/test/build# make
Scanning dependencies of target main
[ 50%] Building CXX object CMakeFiles/main.dir/main.cc.o
[100%] Linking CXX executable main
/usr/bin/ld: CMakeFiles/main.dir/main.cc.o:(.data.rel.ro._ZTV9GatheringI9ImplState9ImplRouteE[_ZTV9GatheringI9ImplState9ImplRouteE]+0x10): undefined reference to `Gathering<ImplState, ImplRoute>::gather(ImplState const&)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/main.dir/build.make:84: main] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/main.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
# CMakeLists.txt
ADD_EXECUTABLE(main
        main.cc
)
// mctsimpl.hpp
#include <vector>

class State {
};

template <class T>
class Action {
    void execute(T&);
};

template <class A>
class Route {
public:
    std::vector<A> actions;

    A getAction();
};

template <class T, class R>
class Gathering {
public:
    virtual R gather(const T&);
};

// Actually this is a MCTS implementation
// But those search methods are omitted here
// I just need to collect some actions
template<class T, class A, class R>
class MCTS {
public:
    MCTS(T& rootData, Gathering<T, R>* gathering) :
        state(rootData),
        gathering(gathering) {
    }

    R gather() {
        return gathering->gather(state);
    }
private:
    Gathering<T, R>* gathering;
    T& state;
};

// mctslib.hpp
#include "mctsimpl.hpp"

class ImplAction;

class ImplRoute;

class ImplState : public State {
public:
    ImplState() :
        i(0) {
    }

    int i;
    std::vector<ImplAction> actions;

    void execute(int i);

    ImplRoute gather() const;
};

class ImplAction : Action<ImplState> {
public:
    ImplAction(int i) :
        i(i) {
    };

    int i;

    void execute(ImplState& state) {
        state.execute(i);
    }
};

class ImplRoute : public Route<ImplAction>{
public:
    ImplRoute(std::vector<ImplAction> actions) :
        actions(actions) {
    }

    ImplAction getAction() {
        return actions[0];
    }

    std::vector<ImplAction> actions;
};

class ImplGathering : public Gathering<ImplState, ImplRoute>{
public:
    ImplGathering() {}

    ImplRoute gather(const ImplState& s) override {
        return s.gather();
    }
};

using ImplMCTS = MCTS<ImplState, ImplAction, ImplRoute>;
// mcts.hpp
#include "mctslib.hpp"

void ImplState::execute(int i) {
    actions.push_back(ImplAction(i));
    this->i = i;
}

ImplRoute ImplState::gather() const {
    return ImplRoute(actions);
}
// main.cc
#include "mcts.hpp"

int main() {
    ImplState state;
    ImplGathering* gathering = new ImplGathering();
    ImplMCTS mcts(state, gathering);

    ImplAction action(1);
    action.execute(state);
    action.execute(state);
    action.execute(state);

    // Use here
    mcts.gather();
}

现在,我提供了简化的代码并添加了链接错误。

C++ 模板 链接器错误 未定义引用

评论

1赞 bolov 8/21/2021
请创建一个最小的可重复示例 - 强调可复制性。使用您当前的代码,我会遇到不同的错误,例如“返回不完整的类型”和“错误的参数数量ImplRM"
2赞 JaMiT 8/21/2021
链接器说它找不到某些模板参数的定义。我也不知所措。您能指出函数的定义在代码中的位置吗?(不是派生类中的定义,而是基类的定义。G<>::func()
0赞 Ken White 8/21/2021
这回答了你的问题吗?为什么在使用模板时会出现“未解析的外部符号”错误?
0赞 fields1631 8/21/2021
@bolov谢谢,我很快就会举个例子
1赞 JaMiT 8/21/2021
您添加了几个缺失的部分,这很好,并且符合最小可重现示例的“可重现”方面。但是,在“最小”方面,您仍有工作要做。例如,如果将 的定义减少到并消除访问 成员的代码,错误是否会消失?如果错误仍然存在,请执行此简化。对每个类重复,直到你只剩下重现相关错误所需的内容。ImplStateclass ImplState {};ImplState

答:

0赞 Top-Master 8/21/2021 #1

使你的类抽象化(通过添加),如下所示:= 0

template <class T, class R>
class Gathering {
public:
    virtual R gather(const T&) = 0;
};