std::basic_string 完全专业化(g++ 冲突)
我正在尝试定义 std::basic_string
的完整专业化char、char_traits
由
标头进行类型定义(在 g++ 中)。
问题是,如果我首先包含
,g++ 会将 typedef 视为 basic_string
的实例化,并给出错误。如果我先做我的专业,那么我就没有问题。
在包含
后,我应该能够定义我的专业化。我必须做什么才能做到这一点?
我的代码:
#include <bits/localefwd.h>
//#include <string> // <- uncommenting this line causes compilation to fail
namespace std {
template<>
class basic_string< char, char_traits<char>, allocator<char> >
{
public:
int blah() { return 42; }
size_t size() { return 0; }
const char *c_str() { return ""; }
void reserve(int) {}
void clear() {}
};
}
#include <string>
#include <iostream>
int main() {
std::cout << std::string().blah() << std::endl;
}
上面的代码工作正常。但是,如果我取消注释第一行 #include
行,则会出现以下编译器错误:
blah.cpp:7: error: specialization of ‘std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ after instantiation
blah.cpp:7: error: redefinition of ‘class std::basic_string<char, std::char_traits<char>, std::allocator<char> >’
/usr/include/c++/4.4/bits/stringfwd.h:52: error: previous definition of ‘class std::basic_string<char, std::char_traits<char>, std::allocator<char> >’
blah.cpp: In function ‘int main()’:
blah.cpp:22: error: ‘class std::string’ has no member named ‘blah’
/usr/include/c++/4.4/bits/stringfwd.h< 的第 52 行/code>:
template<typename _CharT, typename _Traits = char_traits<_CharT>,
typename _Alloc = allocator<_CharT> >
class basic_string;
据我所知,这只是模板的前向声明,而不是 g++ 声称的实例化。
/usr/include/c++/4.4/bits/stringfwd.h
第 56 行:
typedef basic_string<char> string;
据我所知,这只是一个 typedef,也不是一个实例化。
那么为什么这些行与我的代码冲突呢?除了确保我的代码始终包含在
之前,我还能做些什么来解决此问题?
I am trying to define a full specialization of std::basic_string< char, char_traits<char>, allocator<char> >
which is typedef'd (in g++) by the <string>
header.
The problem is, if I include <string>
first, g++ sees the typedef as an instantiation of basic_string
and gives me errors. If I do my specialization first then I have no issues.
I should be able to define my specialization after <string>
is included. What do I have to do to be able to do that?
My Code:
#include <bits/localefwd.h>
//#include <string> // <- uncommenting this line causes compilation to fail
namespace std {
template<>
class basic_string< char, char_traits<char>, allocator<char> >
{
public:
int blah() { return 42; }
size_t size() { return 0; }
const char *c_str() { return ""; }
void reserve(int) {}
void clear() {}
};
}
#include <string>
#include <iostream>
int main() {
std::cout << std::string().blah() << std::endl;
}
The above code works fine. But, if I uncomment the first #include <string>
line, I get the following compiler errors:
blah.cpp:7: error: specialization of ‘std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ after instantiation
blah.cpp:7: error: redefinition of ‘class std::basic_string<char, std::char_traits<char>, std::allocator<char> >’
/usr/include/c++/4.4/bits/stringfwd.h:52: error: previous definition of ‘class std::basic_string<char, std::char_traits<char>, std::allocator<char> >’
blah.cpp: In function ‘int main()’:
blah.cpp:22: error: ‘class std::string’ has no member named ‘blah’
Line 52 of /usr/include/c++/4.4/bits/stringfwd.h
:
template<typename _CharT, typename _Traits = char_traits<_CharT>,
typename _Alloc = allocator<_CharT> >
class basic_string;
As far as I know this is just a forward delcaration of the template, NOT an instantiation as g++ claims.
Line 56 of /usr/include/c++/4.4/bits/stringfwd.h
:
typedef basic_string<char> string;
As far as I know this is just a typedef, NOT an instantiation either.
So why are these lines conflicting with my code? What can I do to fix this other than ensuring that my code is always included before <string>
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
仅当专门化依赖于具有外部链接的用户定义名称时,才允许专门化标准库。
char
不满足此要求,并且您会得到未定义的行为。这在 17.4.3.1 [lib.reserver.names]/1 中指定。
您收到的特定错误是因为您的实现已经实例化了您尝试专门化的模板,并且如果您为任何模板提供专门化,则必须在使用您想要提供的参数实例化模板之前专业化。
14.7.3 [temp.expl.spec]/6
You are only allowed to specialize a standard library if the specialization depends on a user-defined name with external linkage.
char
doesn't meet this requirement and you are getting undefined behaviour.This is specified in 17.4.3.1 [lib.reserver.names]/1.
The particular error that you are getting is because your implementation already instantiates the template that you are trying to specialize and, if you provide a specialization for any template, it must be before the template is ever instantiated with the parameters for which you want to provide the specialization.
14.7.3 [temp.expl.spec]/6
作为一般规则,您不应该在命名空间 std 中定义或专门化除特征类之外的任何内容,并且您当然不应该尝试更改 std::string 底层类型的定义。
您应该在自己的命名空间中创建自己的字符数据类型,而不是专门化 basic_string,然后您应该专门化该类型的 std::char_traits (但命名空间 std 中没有其他内容),然后您应该为用这些实例化的 basic_string 创建一个方便的 typedef您自己的命名空间中的类型(而不是命名空间 std 中的类型,它属于 C++ 标准,用户不应更改)。
As a general rule, you should not define or specialize anything other than a traits class in namespace std, and you certainly should not attempt to change the definition of the underyling type of std::string.
Instead of specializing basic_string, you should create your own character datatype in your own namespace, then you should specialize std::char_traits for that type (but nothing else in namespace std), and then you should make a convenient typedef for basic_string instantiated with those types in your own namespace (not in namespace std, which belongs to the C++ standard and shouldn't be altered by users).