【问题标题】:C++ template, linking stage undefined reference errorC++ 模板,链接阶段未定义的引用错误
【发布时间】:2021-10-22 11:14:20
【问题描述】:

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

我尝试在ImplM类中使用ImplG类的方法func,但是链接器报错。

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

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

【问题讨论】:

  • 请创建一个minimal reproducible example - 强调可复制。使用您当前的代码,我得到不同的错误,例如“返回不完整的类型ImplR”和“M 的参数数量错误”
  • 链接器说它找不到某些模板参数的G&lt;&gt;::func() 的定义。我也不知所措。你能指出你的代码中函数的定义在哪里吗? (不是派生类中的定义,而是基类中的定义。)
  • @bolov 谢谢,我很快就会提供一个例子
  • 您添加了几个缺失的部分,这很好,适合 minimal reproducible example 的“可重现”方面。但是,您在“最小”方面仍有工作要做。例如,如果将ImplState 的定义缩减为class ImplState {}; 并消除访问ImplState 成员的代码,错误是否会消失?如果错误仍然存​​在,则进行此简化。对每个其他类重复,直到您只需要重现有问题的错误。

标签: c++ templates linker-errors undefined-reference


【解决方案1】:

使您的类抽象(通过添加= 0),例如:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 1970-01-01
    • 2013-04-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多