模板 class 调用模板函数 - 链接器错误

Template class calling template function - Linker Error

我正在试验模板 classes 和函数,我 运行 遇到以下错误。我正在尝试使用来自 class RelationShipExpander 的模板 class 从 class Vertex 调用模板函数。下面的 MWE 产生以下链接器错误:

Undefined symbols for architecture x86_64:
  "typeinfo for PipeType", referenced from:
      typeinfo for RelationShipExpander<in> in main.cpp.o
  "vtable for PipeType", referenced from:
      PipeType::PipeType() in main.cpp.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
#include <iostream>
#include <vector>
#include <forward_list>

using namespace std;

// Abbrr
class Vertex;
typedef forward_list<const Vertex*> edge_list;

/*
 * Matching
 */
struct match_first {
    match_first(unsigned value) : value(value) {};

    template<class A>
    bool operator()(const pair<const unsigned, A> &a) {
        return a.first == value;
    }

    unsigned value;
};

/*
 * Edge Indirection
 */
struct in {
    static edge_list& get_list(pair<edge_list, edge_list> &a) {
        return a.first;
    }
};

struct out {
    static edge_list& get_list(pair<edge_list, edge_list> &a) {
        return a.second;
    }
};


class Vertex {
public:
    template<class Direction>
    edge_list &get_edges(unsigned relation_id) {
        auto i = find_if(neigh_set.begin(), neigh_set.end(), match_first(relation_id));

        if (i != neigh_set.end()) {
            return Direction::get_list(i->second);
        }

        // throw except.
    }

private:
    vector<pair<const unsigned, pair<edge_list, edge_list>>> neigh_set;
};



class PipeType {
public:
    /*
     * Mutators
     */
    virtual void Pipe(Vertex& gremlin);
};



template <class Direction>
class RelationShipExpander: PipeType {
public:
    /*
     *  Constructor
     */
    RelationShipExpander(unsigned relationship_id) : relationship_id(relationship_id) {};

    /*
     *  Mutators
     */
    void Pipe(Vertex& gremlin) {
        gremlin.get_edges<Direction>(relationship_id);
    };
private:
    unsigned relationship_id;
};



int main() {
    RelationShipExpander<in> expand_in(1);
}

PipeType 不同的是成员函数好像没有定义。就像编译器说的那样:

"vtable for PipeType", referenced from:
PipeType::PipeType() in main.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.

如果您打算 PipeType 成为一个接口,您可以通过添加 = 0 而不是函数 body 来使该函数成为纯虚函数。你不能只跳过实现,即使它是在派生的 class.

中实现的
class PipeType {
public:
    virtual void Pipe(Vertex& gremlin) = 0;
};

如果您希望 class 实现该功能,您当然必须在某处添加该实现。在 header 或其中一个 .cpp 文件中。