17

所以我有一个很好的持久分配器类persistent_alloc<T>,它允许我在持久内存中分配 C++ 容器对象和字符串,该内存由一个 mmaped 文件支持,该文件可以从我的程序的一次运行持续到下一次。

当我想做任何混合持久性和非持久性对象的事情时,我的问题就来了。例如,我有

typedef std::basic_string<char, std::char_traits<char>, persistent_alloc<char>> pstring;

pstring a, b, c;
std::string x, y, z;

我希望能够执行以下操作:

if (a == x)
    a = y;
c = z + b;

等等,但默认情况下它不起作用,因为pstring它们std::string是不相关的类型。现在就比较而言,我可以定义:

template<typename Alloc1, typename Alloc2> inline bool
operator==(const std::basic_string<char, std::char_traits<char>, Alloc1> &a,
           const std::basic_string<char, std::char_traits<char>, Alloc2> &b)
{
    return strcmp(a.c_str(), b.c_str()) == 0;
}

...现在我可以比较字符串是否相等。但是为每个操作添加这些似乎很痛苦——似乎它们应该由标准库提供。更糟糕的是,赋值运算符和复制构造函数必须是成员,不能像这样定义为全局内联函数。

有没有合理的方法来做到这一点?还是我必须有效地重写整个标准库以有效地支持分配器?

4

1 回答 1

8

有一种方法可以解决这个问题,但你需要跳出框框思考一下。您需要的是一种中间类型,它可以从std::string您的分配器字符串和您的分配器字符串中隐式构造。

目前在 C++ 委员会面前有这样的提议。它基于已存在的 Google 构建的 Apache 许可实现。它被称为basic_string_ref; 它是一个模板类,基本上是一个指向字符串中第一个字符的指针和一个大小,表示字符串的长度。它不是一个真正的容器,因为它不管理内存。

这正是您所需要的。

basic_string_ref对于特定的字符类型和特征类型可以从不std::basic_string 考虑分配器的情况下隐式构造。

所有的比较运算符都可以用 来定义basic_string_ref。由于它可以隐式构造std::basic_string(并且几乎可以自由构造),因此它可以透明地用于不同分配的字符串之间的比较。

做任务相当棘手,但可行。它需要一系列转换:

a = pstring{basic_string_ref{y}};

当然,不是最漂亮的代码。我们宁愿简单地将复制构造函数和赋值运算符更改为与std::basic_string分配器无关。但由于这是不可行的,这确实是次佳的事情。您甚至可以将其包装在模板函数中:

template<typename DestAllocator, typename SourceAllocator, typename charT, typename traits>
std::basic_string<charT, traits, DestAllocator> conv_str(const std::basic_string<charT, traits, SourceAllocator> &input)
{
  return std::basic_string<charT, traits, DestAllocator>{basic_string_ref<charT, traits>{y}};
}

当然,如果你能做到这一点,你可以这样做:

template<typename DestAllocator, typename SourceAllocator, typename charT, typename traits>
std::basic_string<charT, traits, DestAllocator> conv_str(const std::basic_string<charT, traits, SourceAllocator> &input)
{
  return std::basic_string<charT, traits, DestAllocator>{y.begin(), y.end()};
}

如果这只是其中的一部分,那就太好了std::basic_string,这样您就不需要解决方法了。但事实并非如此。

于 2012-05-10T20:38:34.567 回答