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

时间:2010-04-23 21:05:44

标签: c++ templates stl g++ specialization

我正在尝试通过std::basic_string< char, char_traits<char>, allocator<char> >标头定义<string>的完全特化,这是{dede'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;
}

上面的代码工作正常。但是,如果我取消注释第一个#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’

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

  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,而不是实例化。

那么为什么这些行与我的代码冲突?除了确保我的代码始终包含在<string>之前,我该怎么做才能解决此问题?

2 个答案:

答案 0 :(得分:10)

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

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

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

14.7.3 [temp.expl.spec] / 6

答案 1 :(得分:0)

作为一般规则,你不应该在命名空间std中定义或专门化除traits类之外的任何东西,你当然不应该尝试更改std :: string的underyling类型的定义。

您应该在自己的命名空间中创建自己的字符数据类型,而不是专门化basic_string,那么您应该专门为该类型设置std :: char_traits(但在命名空间std中没有其他内容),然后您应该为basic_string创建一个方便的typedef在您自己的命名空间中实例化这些类型(不在命名空间std中,它属于C ++标准,不应被用户更改)。