简体   繁体   English

std :: basic_string完全特化(g ++冲突)

[英]std::basic_string full specialization (g++ conflict)

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. 我试图通过<string>标头定义std::basic_string< char, char_traits<char>, allocator<char> > ,它是typedef'd(以g ++ <string> )。

The problem is, if I include <string> first, g++ sees the typedef as an instantiation of basic_string and gives me errors. 问题是,如果我首先包含<string> ,g ++会将typedef看作basic_string的实例化并给我错误。 If I do my specialization first then I have no issues. 如果我先做专业,那么我没有问题。

I should be able to define my specialization after <string> is included. 我应该能够在包含<string>之后定义我的专业化。 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: 但是,如果我取消注释第一个#include <string>行,我会收到以下编译器错误:

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 : /usr/include/c++/4.4/bits/stringfwd.h第52行:

  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. 据我所知,这只是模板的前向移植,而不是g ++声称的实例化。

Line 56 of /usr/include/c++/4.4/bits/stringfwd.h : /usr/include/c++/4.4/bits/stringfwd.h第56行:

   typedef basic_string<char>    string;

As far as I know this is just a typedef, NOT an instantiation either. 据我所知,这只是一个typedef,也不是一个实例化。

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> ? 除了确保在<string>之前始终包含我的代码之外,我还能做些什么来解决这个问题?

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. char不符合此要求,您将获得未定义的行为。

This is specified in 17.4.3.1 [lib.reserver.names]/1. 这在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 14.7.3 [temp.expl.spec] / 6

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. 作为一般规则,您不应该在命名空间std中定义或专门化除traits类之外的任何内容,并且您当然不应尝试更改std :: string的underyling类型的定义。

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). 您应该在自己的命名空间中创建自己的字符数据类型,而不是专门化basic_string,然后您应该专门为该类型设置std :: char_traits(但在命名空间std中没有其他任何内容),然后您应该为basic_string实现一个方便的typedef实例化您自己的命名空间中的类型(不在命名空间std中,它属于C ++标准,不应由用户更改)。

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

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