Учитывая объект класса std::basic_string<char, std::char_traits<char>,my_allocator<char> >
, как вы передадите его сторонней функции, которая ожидает постоянной ссылки на объект класса std::string
без каких-либо копий?
Я думаю, что если мы возьмем распределитель без состояний, тогда теоретически два типа должны быть точно такими же во время выполнения. Поэтому можно просто повторить интерпретацию типа, например:
// my_allocator template is some place else...
typedef std::basic_string< char, std::char_traits<char>,
my_allocator<char> > my_string;
void third_party_foo(const std::string &s);
int main()
{
const my_string str = "Hello, world!";
third_party_foo(*(const std::string *)&str);
}
Учитывая распределитель, у которого есть состояние (которое мы можем иметь с С++ 11), я бы предположил, что это намного опаснее, поскольку размеры и макет этих классов во время выполнения могут быть разными. Если я до сих пор прав, скажем, что размеры объекта двух классов одинаковы, в этом случае я мог предположить, что состояние распределителя подходит, скажем, к некоторой области, которая в противном случае была бы дополнена, и в этом случае первый подход может работать.
Насколько я могу поставить под угрозу этот подход, практически говоря? Существуют ли какие-либо альтернативы, которые не имеют накладных расходов во время выполнения (и, конечно, не требуют изменения стороннего интерфейса и/или отказа от строки с помощью пользовательского распределителя)?
Нет. Используя пользовательский распределитель, вы используете другой тип от std::string
. И нет (законного) способа в С++ преобразовать это без копии. Все, что, по вашему мнению, может работать, не гарантируется стандартом С++.
Итак, вы должны признать, что вам нужна копия.
rebind
которая может быть использована для безопасного приведения типов как с распределителями.