Пользовательские операторы преобразования C ++ без классов? - PullRequest
6 голосов
/ 24 октября 2009

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

Вот мой пример использования: я работаю с библиотекой C, которая выдает мне PA_Unichar *, где библиотека определяет PA_Unichar как 16-битное целое число. На самом деле это строка, закодированная в 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), которые могут быть или не быть типами классов?

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

Ответы [ 4 ]

8 голосов
/ 24 октября 2009

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

std::string convert(PA_Unichar *libOutput);

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

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

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

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

5 голосов
/ 24 октября 2009

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

4 голосов
/ 24 октября 2009

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

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
3 голосов
/ 25 октября 2009

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

...