0

我在自己的图书馆工作,我有自己的分配器。我已经声明了一个这样的通用接口:

class MyAllocator
{
public:
  void * allocate(size_t size);
  void * allocate(size_t size, size_t align);
  void   deallocate(void *);

  //...

};

现在,如果我想用这样的分配器分配 C++ 对象,我必须以这种方式使用放置 new:

MyAllocator a;
MyObject * o = new(a.allocate(sizeof(MyObject))) MyObject(param1, param2, ...);

当然,这很好用。现在,前段时间我想做一个全局分配器,它将分配器作为参数,以避免重复的 sizeof()。所以我来了:

template< typename AllocatorT >
inline
void *operator new(size_t n_bytes, AllocatorT & allocator)
{
    return allocator.allocate(n_bytes);
}

有了这个,我可以打电话:

MyAllocator my_alloc;
MyObject * o = new(my_alloc) MyObject(param1, param2);

语法很干净,很酷。这基本上也可以很好地工作(使用 gcc 和 msvc2010),但是今天,当我在 msvc2008 中尝试它时,我遇到了错误:这是因为 msvc2008 编译器被该模板参数愚弄了,所以,当我包含一个使用的标头时正常放置 new [几乎每个 stl 标头都包含对放置 new 的调用,例如 vector、set 等] 编译器将使用我的全局 new 模板版本,而不是放置 new,从而导致明显错误:a type 'void *' 不是类/结构,当然也没有 allocate() 成员函数。

现在,问题出现了:

  • 这是msvc2008的bug吗?使用 gcc 4.4.0、4.4.5 和 msvc2010 运行良好。
  • 我在编写一个接受分配器引用的模板化全局 new 运算符时错了吗?我的意思是,这东西会不会是一种模棱两可的语法,很容易让编译器愚弄,经常导致错误,我应该放弃这个想法,或者这可以通过其他方式实现吗?如前所述,它通过使用常规放置 new 的自定义分配器大大降低了 C++ 对象分配的复杂性。
  • 通常,如果我们有:

    无效f(无效*);//1 模板< typename A >f(A &); //2

我们称:

void * void_ptr = something();
f(void_ptr);

当然这里第一个版本被调用。

为什么在 msvc2008 中使用 operator new 的模板版本似乎不会发生这种情况?

4

0 回答 0