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

时间:2017-03-28 15:42:51

标签: c++ templates linker-errors

我正在尝试使用模板类和函数,但遇到了以下错误。我尝试使用类RelationShipExpander中的模板类从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);
}

1 个答案:

答案 0 :(得分:1)

PipeType 的不同之处在于成员函数似乎没有定义。就像编译器说的那样:

  

“管道类型的vtable”,引自:         main.cpp.o中的PipeType :: PipeType()
    注意:缺少vtable通常意味着第一个非内联虚拟成员函数没有定义。

如果您希望PipeType成为一个界面,可以通过添加= 0而不是函数体来使该函数成为纯虚函数。您不能跳过实现,即使它是在派生类中实现的。

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

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