非模板错误的模板定义
Template definition of non-template error
我想将 CRTP pattern 与一些锁定机制结合使用以在多线程环境中进行访问同步。
我的代码如下所示:
//-- 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" }
}
不过我得到
error: template definition of non-template std::unordered_map<int, std::basic_string<char> > Base<ProductX<SYNC>, SYNC>::s_map
编译时。
静态 s_map
初始化引发错误。有人可以指出我做错了什么吗?
您在 s_map
的定义中使用 Base<ProductX<SYNC>, SYNC>
作为成员特化,因此您实际上需要 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.
一个简化的例子。
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;
一切都好起来了。
C++ 允许这样做:
template<typename SYNC>
std::unordered_map<int, std::string> Base<ProductX<SYNC>, SYNC>::s_map { };
仅适用于相应的部分模板 class 专业化。为此,请查看 Columbo 和 n.m 的回复。下面的用户。然而,缺点是您必须为您以这种方式创建的每个 ProductX
class 重新定义所有内容。 IE。在我的例子中,如果我想创建 classes ProductX
、ProductY
、ProductZ
,我将不得不为它们中的每一个定义偏特化,包括所有成员函数等等,恕我直言,这不是很实用。
如果我们不想编写整个 class 专业化,我们必须使用没有规范模板定义的静态变量:
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";
}
这个可以正常编译。
我要感谢 Columbo 和 'n.m.' 的回复并为我指明了正确的方向!我会 select 你的答案,但我想在不编写 class 模板专业化的情况下展示这个解决方案。
我想将 CRTP pattern 与一些锁定机制结合使用以在多线程环境中进行访问同步。
我的代码如下所示:
//-- 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" }
}
不过我得到
error: template definition of non-template
std::unordered_map<int, std::basic_string<char> > Base<ProductX<SYNC>, SYNC>::s_map
编译时。
静态 s_map
初始化引发错误。有人可以指出我做错了什么吗?
您在 s_map
的定义中使用 Base<ProductX<SYNC>, SYNC>
作为成员特化,因此您实际上需要 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.
一个简化的例子。
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;
一切都好起来了。
C++ 允许这样做:
template<typename SYNC>
std::unordered_map<int, std::string> Base<ProductX<SYNC>, SYNC>::s_map { };
仅适用于相应的部分模板 class 专业化。为此,请查看 Columbo 和 n.m 的回复。下面的用户。然而,缺点是您必须为您以这种方式创建的每个 ProductX
class 重新定义所有内容。 IE。在我的例子中,如果我想创建 classes ProductX
、ProductY
、ProductZ
,我将不得不为它们中的每一个定义偏特化,包括所有成员函数等等,恕我直言,这不是很实用。
如果我们不想编写整个 class 专业化,我们必须使用没有规范模板定义的静态变量:
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";
}
这个可以正常编译。
我要感谢 Columbo 和 'n.m.' 的回复并为我指明了正确的方向!我会 select 你的答案,但我想在不编写 class 模板专业化的情况下展示这个解决方案。