2009-10-24 7 views
5

В C++ можно определить операторы преобразования, которые не являются членами класса? Я знаю, как это сделать для обычных операторов (например, +), но не для операторов преобразования.C++ пользовательские операторы преобразования без классов?

Вот мой прецедент: я работаю с библиотекой C, которая передает мне PA_Unichar *, где библиотека определяет PA_Unichar как 16-битный int. На самом деле это строка, закодированная в UTF-16. Я хочу преобразовать его в std::string, закодированный в UTF-8. У меня есть весь код преобразования готовый и рабочий, и я только не хватает синтаксический сахар, который позволил бы мне написать:

PA_Unichar *libOutput = theLibraryFunction(); 
std::string myString = libOutput; 

(как правило, в одной строке без переменной TEMP).

Также стоит отметить:

  • Я знаю, что std::string не определяет неявное преобразование из char*, и я знаю, почему. Та же причина может быть применена здесь, но это не относится к делу.

  • У меня есть ustring, подкласс std::string, который определяет правильного оператора преобразования от PA_Unichar*. Он работает, но это означает использование переменных ustring вместо std::string и что тогда требует преобразования в std::string, когда я использую эти строки с другими библиотеками. Так что это не очень помогает.

  • Использование оператора присваивания не работает, поскольку те должны быть быть членами класса.

Так же можно определить неявные операторы преобразования между двумя типами вы не контролируете (в моем случае PA_Unichar* и std::string), которые могут или не могут быть типами классов?

Если нет, то какие могут быть обходные пути?

ответ

8

Что случилось с бесплатной функцией?

std::string convert(PA_Unichar *libOutput); 

std::string myString = convert(theLibraryFunction()); 

Редактировать в ответ на комментарий:

Как DrPizza says: Все остальные пытаются заткнуть дыры открыли неявные преобразования путем замены их с теми явного преобразования, которые вы называете «визуальный беспорядок».

Что касается временной строки: просто дождитесь следующей версии компилятора. Вероятно, он будет иметь ссылки на rvalue, а его реализация std::string реализует семантику перемещения поверх нее, что исключает копию. Мне еще предстоит увидеть более дешевый способ ускорить ваш код, чем просто перейти на новую версию компилятора.

+0

что не так? Не много, но все же, две вещи: - визуальный беспорядок, когда у вас есть сотни бессмысленных звонков для преобразования - это решение подразумевает использование временной std :: string. Это означает, что данные копируются дважды, все время. Это может быть или не быть проблемой, но не очень удовлетворительно. –

+6

Большинство компиляторов оптимизируют дополнительную копию. – rlbond

+4

jdmuys> rlbond прав, RVO является обычным и реальным на практике. Вы можете сделать это так: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ – Klaim

4

Я не думаю, что вы можете определить «глобальные» операторы преобразования. Стандарты говорят, что conversion functions являются special member functions. Я бы propse следующего, если я мог бы рассмотреть следующий синтаксис сахар:

struct mystring : public string 
{ 
    mystring(PA_Unichar * utf16_string) 
    { 
     // All string functionality is present in your mystring. 
     // All what you have to do is to write the conversion process. 
     string::operator=("Hello World!"); 
     string::push_back('!'); 
     // any string operation... 
    } 
}; 

Имейте в виде, что полиморфное поведение этого класса нарушается.Пока вы не создаете его объект с помощью указателя типа string*, вы находитесь в безопасности! Таким образом, этот код является идеальным:

mystring str(....); 

Как уже говорилось, следующий код нарушен!

string* str = new mystring(....); 
.... 
delete str; // only deleting "string", but not "mystring" part of the object 
// std::string doesn't define virtual destructor 
5

Неявные преобразования - это дьявол, во всяком случае. Сделать это явным с помощью вызова функции преобразования.

+4

Ну, это зависит. Существуют реальные ситуации, когда подразумеваемые преобразования имеют смысл. Я обычно использую их, например, для преобразования одного типа в другой, который в семантических терминах является подмножеством другого. Например, если у вас есть класс 'person' и' employee', я бы ожидал, что 'employee' автоматически преобразуется в' person', где ожидается последний. (Конечно, неявное преобразование в другую сторону было бы плохой идеей, с другой стороны.) – Mephane

+1

Я понимаю, что вы просто предложили гипотетический пример, но работник как подкласс человека - плохой дизайн и домашнее животное мой. Подклассификация используется для отношений is-a. Кажется, что работник - это человек, но на самом деле это лишь часть двусмысленности английской грамматики. Сотрудник не является особым типом человека, а является ролью, которую может иметь человек. На самом деле это отношения. – 2012-10-17 14:51:33

3

Нет, вы не можете. То, что вы могли бы сделать в качестве альтернативы, - создать конструктор преобразования в целевом классе (не ваш случай, так как вы хотите преобразовать в std :: string), если только не вывести его). Но я согласен с другими ответами, я думаю, что неявное преобразование не рекомендуется в этом случае - особенно потому, что вы не конвертируете его из объекта, а из указателя. Лучше иметь свободную функцию, ваш код будет легче понять, и следующий программист, наследующий код, наверняка поблагодарит вас.

 Смежные вопросы

  • Нет связанных вопросов^_^