提供模板类的一种方法的定义
Posted
技术标签:
【中文标题】提供模板类的一种方法的定义【英文标题】:Provide definition of one method of a template class 【发布时间】:2015-01-15 20:07:32 【问题描述】:是否可以提供模板类的方法之一的自定义定义。或者是全部还是全部,这意味着我必须按原样使用所有提供的定义,或者我必须创建/定义整个类的模板特化。
我正在编写一些测试代码以更好地理解编写自定义分配器。我想提供allocator::allocate() 的自定义定义。我是否必须转发声明分配器。还是我的 allocate() 原型错误?还是我必须为分配器提供模板特化,这样我才能提供自己的 allocate() 定义。
#include <memory>
#include <iostream>
template <>
std::allocator<int>::pointer
std::allocator<int>::allocate(size_type n, std::allocator<void>::const_pointer hint)
cout << "Doing an alloc for an int allocator" << endl;
return nullptr;
int main()
std::allocator<int> a1; // default allocator for ints
int* a = a1.allocate(10); // space for 10 ints
得到以下错误:
$ g++ -std=c++11 ./t1.cc
./t1.cc:6:78: error: no member function 'allocate' declared in 'std::allocator<int>'
我正在使用 g++ 4.7.2。我查看了头文件“bits/allocator.h”(包含在定义类分配器的“内存”中。没有看到方法 allocate()。方法原型是否在基类之一中?
【问题讨论】:
你必须把它放到 std 命名空间中。 C++ 中没有模板函数特化。 (取而代之的是重载,在这种情况下对您没有帮助) @erenon 在 std 命名空间中放入“什么”? 【参考方案1】:这是因为在 gcc 中,allocator
是这样定义的:
template<typename _Tp>
class allocator: public __glibcxx_base_allocator<_Tp>
.. ;
allocate()
方法本身来自__glibcxx_base_allocator
。现在,几行之后,这个基础就被删除了:
// Undefine.
#undef __glibcxx_base_allocator
作为阻止像你这样的人在代码中乱搞的气馁!
但是,让我以 DO NOT DO THIS EVER OMG 作为开头,为了胡闹,你可以发现 __glibcxx_base_allocator
是 #define
d 为 __gnu_cxx::new_allocator
,并且您可以使用这些知识来专门化您的功能(请注意,它必须与原始模板位于相同的命名空间中 - 根据专业化规则):
namespace __gnu_cxx
template <>
new_allocator<int>::pointer
new_allocator<int>::allocate(
new_allocator<int>::size_type n,
std::allocator<void>::const_pointer hint)
std::cout << "Doing an alloc for an int allocator" << std::endl;
return nullptr;
我真的无法强调不要这样做。但是追踪起来很有趣。
【讨论】:
太棒了,非常感谢。是一次非常好的学习经历。我有个问题。当我使用 std::allocator查看 MinGW g++4.9 附带的 libstdc++ 标头,allocate
成员函数的定义存在于标头 ext/new_allocator.h
中定义的类 new_allocator
中。 std::allocator
公开继承自 new_allocator
。
如果 libstdc++ 选择将 allocate
定义为 std::allocator
本身的成员函数,您的代码将被编译(它在 VS2013 上编译,因为 std::allocator
的实现确实定义了 allocate
成员函数),但是即便如此,这将是未定义的行为。
来自 N3337,§17.6.4.2.1/2 [namespace.std]
如果 C++ 程序声明了,则其行为未定义 — 标准库类模板的任何成员函数的显式特化,或
...
如果您想自定义行为,您需要提供自己的分配器实现。
【讨论】:
只是好奇,再想一想,为什么代码会在你的环境下编译。编译器不应该抱怨 std::allocatorstd::allocator<int>
的专门化
当你说代码在 VS2013 中编译时,因为 std::allocator 定义了 allocate()。在那种情况下,当我在 main 中使用类型 allocator以上是关于提供模板类的一种方法的定义的主要内容,如果未能解决你的问题,请参考以下文章