我希望将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
初始化引发错误。有人能指出我做错了吗?
答案 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" }
};
答案 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浏览器。在我的情况下,如果我想创建类ProductY
,ProductZ
,template<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;他们的回复和指向正确的方向!我会选择你的答案,但我想在没有编写类模板专业化的情况下展示这个解决方案。