简体   繁体   English

模板定义非模板错误

[英]Template definition of non-template error

I want to use the CRTP pattern in combination with some locking mechanism for access syncing in multithreaded environment. 我想将CRTP模式与一些锁定机制结合使用,以便在多线程环境中进行访问同步。

My code looks like this: 我的代码看起来像这样:

//-- 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" }
}

However I get 但是我得到了

error: template definition of non-template std::unordered_map<int, std::basic_string<char> > Base<ProductX<SYNC>, SYNC>::s_map 错误:非模板的模板定义std::unordered_map<int, std::basic_string<char> > Base<ProductX<SYNC>, SYNC>::s_map

when compiling. 编译时

The error is raised for the static s_map initialisation. 针对静态s_map初始化引发了错误。 Can someone point me what I'm doing wrong? 有人能指出我做错了什么吗?

You use Base<ProductX<SYNC>, SYNC> as the members specialization in the definition of s_map , so you actually need a corresponding partial specialization of Base (§14.5.5.3/1). 您使用Base<ProductX<SYNC>, SYNC>作为s_map定义中的成员s_map ,因此您实际上需要Base的相应部分特化(§14.5.5.3/ 1)。 In other words, you're trying to define a member of a non-existent partial specialization. 换句话说, 您正在尝试定义不存在的部分特化的成员。

Try providing that specialization: 尝试提供专业化:

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 . 演示

A simplified example. 一个简化的例子。

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

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

However 然而

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

The latter definition belongs to a partial specialization of C which does not exists. 后一个定义属于C的部分特化,它不存在。 Create one: 创建一个:

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

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

and all is well again. 一切都很好。

C++ allows this: C ++允许这样:

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

only with corresponding partial template class specialisation. 只有相应的部分模板类专门化。 To do these, please check out responses of Columbo and nm users below. 要做到这些,请查看以下Columbo和nm用户的回复。 However, disadvantage is that you have to re-define everything for every ProductX class you create this way. 但是,缺点是您必须为这种方式创建的每个ProductX类重新定义所有内容。 Ie. IE浏览器。 in my case, if I want to create classes ProductX , ProductY , ProductZ , I will have to define partial specialisation for each one of them, including all member functions etc, which is not very practical IMHO. 在我的情况下,如果我想创建类ProductXProductYProductZ ,我将必须为它们中的每一个定义部分特化,包括所有成员函数等,这是不太实用的恕我直言。

In case we don't want to write whole class specialisation, we have to use either static variable with no-spec template definition: 如果我们不想编写全类专门化,我们必须使用静态变量和无规范模板定义:

template<typename T, typename SYNC>
std::unordered_map<int, std::string> Base<T, SYNC>::s_map { };

or fully specialised template definition: 或完全专业的模板定义:

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

Here is full example with full template specialisation: 以下是完整模板专业化的完整示例:

//-- 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";
}

This one will compile fine. 这个编译好了。

I'd like to thank Columbo and 'nm' for their replies and for pointing me in right direction! 我要感谢Columbo和'nm'的回复,并指出我正确的方向! I would select your answers, but I wanted to show this solution without writing class template specialisation. 我会选择你的答案,但我想在没有编写类模板专业化的情况下展示这个解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM