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

Soa*_*Box 4 c++ templates stl g++ specialization

我试图std::basic_string< char, char_traits<char>, allocator<char> >通过<string>标题定义一个完整的特化,其中typedef'd(以g ++为单位).

问题是,如果我<string>首先包含,g ++会将typedef视为实例化basic_string并给我错误.如果我先做专业,那么我没有问题.

我应该能够在<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;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码工作正常.但是,如果我取消注释第一#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’
Run Code Online (Sandbox Code Playgroud)

第52行/usr/include/c++/4.4/bits/stringfwd.h:

  template<typename _CharT, typename _Traits = char_traits<_CharT>,
           typename _Alloc = allocator<_CharT> >
    class basic_string;
Run Code Online (Sandbox Code Playgroud)

据我所知,这只是模板的前向移植,而不是g ++声称的实例化.

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

   typedef basic_string<char>    string;
Run Code Online (Sandbox Code Playgroud)

据我所知,这只是一个typedef,也不是一个实例化.

那么为什么这些行与我的代码冲突呢?除了确保以前始终包含我的代码之外,我还能做些什么来解决这个问题<string>

CB *_*ley 10

如果专业化取决于具有外部链接的用户定义名称,则仅允许专门化标准库.char不符合此要求,您将获得未定义的行为.

这在17.4.3.1 [lib.reserver.names]/1中指定.

您获得的特定错误是因为您的实现已经实例化了您尝试专门化的模板,并且如果您为任何模板提供专门化,则必须在模板实例化之前使用您要提供的参数专业化.

14.7.3 [temp.expl.spec]/6

  • ISO C++ 03 17.4.3.1"保留名称":除非另有说明,否则C++程序未定义向命名空间std中的命名空间std或命名空间添加声明或定义.程序可以将任何标准库模板的模板特化添加到命名空间std.标准库模板的这种特化(完整或部分)会导致未定义的行为,除非声明依赖于用户定义的外部链接名称,除非特化符合原始模板的标准库要求.) (2认同)