4

我正在尝试std::basic_string< char, char_traits<char>, allocator<char> >通过标题定义一个完整的专业化,它是 typedef'd (在 g++ 中)<string>

问题是,如果我<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’

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

  template<typename _CharT, typename _Traits = char_traits<_CharT>,
           typename _Alloc = allocator<_CharT> >
    class basic_string;

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

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

   typedef basic_string<char>    string;

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

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

4

2 回答 2

9

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

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

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

14.7.3 [temp.expl.spec]/6

于 2010-04-23T21:10:49.487 回答
0

作为一般规则,您不应该在命名空间 std 中定义或专门化除特征类之外的任何内容,并且您当然不应该尝试更改 std::string 的底层类型的定义。

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

于 2010-04-23T21:18:30.000 回答