С++: эффективный swap() при использовании настраиваемого распределителя

Кажется, это месяц шаблонов С++ для меня...

У меня есть SecureString. SecureString выглядит так же, как std::string, за исключением того, что использует собственный распределитель, который обнуляет при уничтожении:

class SecureString
{
public:
  typedef std::basic_string< char, std::char_traits<char>, zallocator<char> > SecureStringBase;
  typedef zallocator<char>::size_type size_type;
  static const size_type npos = static_cast<size_type>(-1);
  ....
private:
  SecureStringBase m_base;
};

Полный код для SecureString можно найти по адресу http://code.google.com/p/owasp-esapi-cplusplus/source/browse/trunk/esapi/util/SecureString.h; и код для распределителя можно найти в http://code.google.com/p/owasp-esapi-cplusplus/source/browse/trunk/esapi/util/zAllocator.h.

В настоящее время мы определили swap, который принимает std::string в качестве аргумента:

void SecureString::swap(std::string& str)
{
  SecureStringBase temp(str.data(), str.size());
  m_base.swap(temp);
  str = std::string(temp.data(), temp.size());
}

Я чувствую, что у меня нет возможности в swap, потому что базовые типы отличаются только распределителями. Может ли кто-нибудь увидеть способ избежать временного? Можно ли использовать rebind для ускорения этого запуска?

EDIT: SecureString::swap(std::string& str) теперь исчез. Ссылка на функцию в этом потоке осталась на месте для потомков.

Джефф

Ответы

Ответ 1

К сожалению... нет.

Это не для rebind. rebind используется потому, что распределитель предназначен для размещения объектов одного типа и только одного типа (std::allocator<T>) в STL.

Однако есть трюк. Например, когда вы создаете экземпляр std::list<T, std::allocator<T>>, тогда allocator не нужно выделять T s, он должен выделять некоторую внутреннюю структуру, а не как __list_node<T>, и именно тогда, когда rebind используется, это создает новый распределитель, родственный экземпляр предиката (они отличаются только параметром шаблона и, вероятно, используют один и тот же пул памяти под обложками).

В вашем случае, однако, ваш распределитель и распределитель std::string отличаются друг от друга, и поэтому они не могут обмениваться памятью. Поэтому вам нужно сделать копию.

Вы можете оптимизировать операцию void swap(SecureString&, SecureString&), но не эту.

Один вопрос: почему бы не typedef std::string<char, SecureAllocator<char>> SecureString;?