模板定义非模板错误

时间:2015-07-22 07:58:25

标签: c++ templates generic-programming crtp

我希望将CRTP pattern与一些锁定机制结合使用,以便在多线程环境中进行访问同步。

我的代码如下所示:

obj[cond]

但是我得到了

  

错误:非模板//-- CRTP base class with some sync/lock mechanism template<typename T, typename SYNC> struct Base { static std::unordered_map<int, std::string> s_map; static SYNC s_sync; }; //-- derived class using CRTP template<typename SYNC> struct ProductX : public Base<ProductX<SYNC>, SYNC> {}; //-- static initialisation template<typename SYNC> std::unordered_map<int, std::string> Base<ProductX<SYNC>, SYNC>::s_map { { 1, "value_1" }, { 2, "value_2" } } 的模板定义

编译时

静态std::unordered_map<int, std::basic_string<char> > Base<ProductX<SYNC>, SYNC>::s_map初始化引发错误。有人能指出我做错了吗?

3 个答案:

答案 0 :(得分:8)

您使用Base<ProductX<SYNC>, SYNC>作为s_map定义中的成员专精,因此您实际上需要Base(§14.5.5.3/ 1)的相应部分特化。换句话说,您正在尝试定义不存在的部分特化的成员。

尝试提供专业化:

template<typename SYNC>
struct ProductX;

//-- CRTP base class with some sync/lock mechanism
template<typename T, typename SYNC>
struct Base {};
template<typename SYNC>
struct Base<ProductX<SYNC>, SYNC> {
  static std::unordered_map<int, std::string> s_map;
  static SYNC s_sync;
};

//-- derived class using CRTP
template<typename SYNC>
struct ProductX : public Base<ProductX<SYNC>, SYNC> {};

//-- static initialisation
template<typename SYNC>
std::unordered_map<int, std::string> Base<ProductX<SYNC>, SYNC>::s_map {
  { 1, "value_1" },
  { 2, "value_2" }
};

Demo

答案 1 :(得分:4)

一个简化的例子。

template <class A, class B>
struct C
{
    static int x;
};

template <class A, class B> int C<A, B>::x = 0; // this works

然而

template <class A> int C<A, double>::x = 0; // same error as yours

后一个定义属于C的部分特化,它不存在。创建一个:

template <class A>
struct C<A, double>
{
    static int x;
};

template <class A> int C<A, double>::x = 1;

一切都很好。

答案 2 :(得分:0)

C ++允许这样:

ProductX

仅限相应的部分模板类专门化。要做到这些,请查看Columbo和上午的回复。以下用户。但是,缺点是您必须为这种方式创建的每个ProductX类重新定义所有内容。 IE浏览器。在我的情况下,如果我想创建类ProductYProductZtemplate<typename T, typename SYNC> std::unordered_map<int, std::string> Base<T, SYNC>::s_map { }; ,我将必须为它们中的每一个定义部分特化,包括所有成员函数等,这不是非常实用的恕我直言。

如果我们不想编写全班专业化,我们必须使用静态变量和无规格模板定义:

struct NoSync { };
template<typename NoSync>
std::unordered_map<int, std::string> Base<ProductX<NoSync>, NoSync>::s_map { };

或完全专业的模板定义:

//-- CRTP base class with some sync/lock mechanism
template<typename T, typename SYNC>
struct Base {
  static std::unordered_map<int, std::string> s_map;
  static SYNC s_sync;
  static std::string& value_name1(int value) { return s_map[value]; }
};

//-- derived class using CRTP
template<typename SYNC>
struct ProductX : public Base<ProductX<SYNC>, SYNC> {};

struct NoSync {};

//-- static initialisation
template<>
std::unordered_map<int, std::string> Base<ProductX<NoSync>, NoSync>::s_map {
  { 1, "value_1" },
  { 2, "value_2" }
};

int main() {
  ProductX<NoSync> p;
  std::cout << "Value: " << p.s_map[1] << "\n";
  std::cout << "Value: " << p.value_name1(2) << "\n";
}

以下是完整模板专业化的完整示例:

{{1}}

这个编译好了。

我要感谢Columbo和&#n; m.m。&#39;他们的回复和指向正确的方向!我会选择你的答案,但我想在没有编写类模板专业化的情况下展示这个解决方案。