模板的私有静态变量成员的未定义符号

时间:2014-05-21 01:11:11

标签: c++ templates undefined instantiation static-members

我有一个奇怪的问题。我想实现类似于(https://stackoverflow.com/a/582456/3449968)的东西来按名称检索C ++对象。但我的对象使用模板。所以这是我的修改:

template <int dim>
class AspenFunction: public Function <dim>
{
  // define the type of the map to handle all functions
  typedef std::map<std::string, AspenFunction<dim>*(*)()> map_type;

  static AspenFunction * create_aspen_function (const std::string& s)
  {
    typename map_type::iterator it = getMap()->find(s);
    AssertThrow(it == getMap()->end(), ExcMessage("The aspen_function name '" + s + "' is not registered."));
    return it->second();
  }

protected:
  static map_type * getMap()
  {
    if (!_map)
      _map = new map_type;
    return _map;
  }

private:
  static map_type * _map;
};


template <typename T, int dim>
AspenFunction<dim> * createT() { return new T; }

template <typename T, int dim>
class Registrar: AspenFunction <dim>
{
public:
  Registrar(const std::string& s)
  {
    AspenFunction<dim>::getMap()->insert(std::make_pair(s, &createT<T, dim>));
  }
};

template class AspenFunction<2>;

编译时,我得到了

Linking CXX executable nssolver
Undefined symbols for architecture x86_64:
   "AspenFunction<2>::_map", referenced from:
      AspenFunction<2>::getMap() in main.cc.o

所以,我尝试通过添加以下内容来实例化_map

template <> AspenFunction<2>::map_type * AspenFunction<2>::_map;

但是我收到以下错误:

/include/equation_handler.h:94:62: error: explicit specialization of '_map' after instantiation
  template <> AspenFunction<2>::map_type * AspenFunction<2>::_map;
                                                             ^
/include/equation_handler.h:69:14: note: implicit instantiation first required here
        if (!_map)
             ^

我不知道还能做什么。我错过了什么吗?

我使用以下编译器

Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

1 个答案:

答案 0 :(得分:2)

您只是声明了static数据成员_map,它缺少定义。在类定义之后立即添加定义(最好)。

template <int dim>
typename AspenFunction<dim>::map_type *AspenFunction<dim>::_map;

但是,我完全取消了数据成员并将getMap()功能更改为

static map_type& getMap()
{
  static map_type instance;
  return instance;
}

instance对象将在第一次调用getMap()时创建,而C ++ 11保证实例化是线程安全的。