[英]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" }
};
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. 在我的情况下,如果我想创建类
ProductX
, ProductY
, ProductZ
,我将必须为它们中的每一个定义部分特化,包括所有成员函数等,这是不太实用的恕我直言。
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.