【发布时间】:2010-04-23 21:05:43
【问题描述】:
我正在尝试通过 <string> 标头定义 std::basic_string< char, char_traits<char>, allocator<char> > 的完整专业化(在 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> 之前包含之外,我还能做些什么来解决这个问题?
【问题讨论】:
-
给我们更大的图景,这样你就可以避免这场灾难:/
-
顺便说一句:“据我所知,这只是模板的前向声明” - 它不是。通过使用
extern template(在 C++03 中是非标准但被广泛接受的扩展,在 C++0x 中是标准的)来实现将在其他地方实例化的模板的前向声明。没有extern,它是一个“显式模板实例化”,如 ISO C++03 14.7.2 中所述 -
@GMan:我真正想要的是玩弄不同的字符串策略(如 COW)。显然,我可以创建自己的课程,但我希望因为它旨在成为 std::string 的直接替代品,它实际上会插入并替换它,甚至不需要任何代码修改,除了额外的包含。
-
@GMan,Soap:看看这个:drdobbs.com/cpp/…
-
@Pavel,不正确。他展示的实际上是一个模板的前向声明。你展示的(“外部模板”)是一个显式的实例化声明(并且将在 C++0x 中)。前向声明并不是要停止实例化,而是要在事实之前引入名称。这就是他展示的代码所做的,这就是“外部模板”所做的不是。
标签: c++ templates stl g++ specialization