Как преобразовать типы в C++?

В своем проекте я использую две разные библиотеки, и обе они предоставляют базовый прямоугольник struct. Проблема в том, что, похоже, нет способа вставить преобразование между типами, поэтому я не могу вызвать функцию в одной библиотеке с результатом функции в другой. Если бы я был автором любого из них, я мог бы создавать конверсии извне, я не могу.

библиотека а:

typedef struct rectangle { sint16 x; sint16 y; uint16 w; uint16 h; } rectangle;

библиотека b:

class Rect {
  int x; int y; int width; int height;
  /* ... */
};

Теперь я не могу сделать преобразователь class, потому что C++ будет искать преобразование только за один шаг. Вероятно, это хорошо, потому что будет много возможностей, связанных с созданием новых объектов всех типов.

Я не могу сделать оператора, который берет struct из a и предоставляет объект class из b:

foo.cpp:123 error: ‘operator b::Rect(const rectangle&)’ must be a nonstatic member function

Итак, есть ли разумный способ обойти это?

редактировать:

Я, возможно, также должен отметить, что мне действительно нужно какое-то решение, которое сделает работу с результатом безупречно, поскольку я не ожидаю, что буду этим кодером. (Хотя я согласен, старая школа, явное преобразование было бы хорошим выбором. Другая ветка, reinterpret_cast, имеет ту же проблему ..)

edit2:

На самом деле, ни одно из предложений не отвечает на мой вопрос, Конрад Рудольф кажется правильным. C++ на самом деле не может этого сделать. Отстой, но это правда. (Если это имеет значение, я попробую создать подкласс, как это предлагает CodingTheWheel.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
1 253
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

Даже это предполагает, что вы создаете одну или обе библиотеки.

Также возможно, что вы совсем не хотите этого делать, но хотите пересмотреть какое-то раннее решение. Или нет.

Если бы struct были такими же внутренне, вы могли бы сделать reinterpret_cast; однако, поскольку похоже, что у вас есть 16-битные или 32-битные поля, вы, вероятно, застряли при преобразовании каждого вызова или написании оболочки для всех функций одной из библиотек.

Почему бы не сделать что-то простое вроде этого: (обратите внимание, что это может / вероятно не будет компилироваться), но вы поняли ...


private Rect* convert(const rectangle& src)
{
    return new Rect(src.x,src.y,src.w,src.h);
}
int main()
{
    rectangle r;
    r.x = 1;
    r.y = 2;
    r.w = 3;
    r.h = 4;

    Rect* foo = convert(&r);
    ...
    delete foo;

}

Обновлено: Похоже на Коко и у меня такая же идея.

Может, можно попробовать с перегрузкой оператора? (Может быть, оператор =, который не является методом вашего класса)?

Оператор Rect = (const Rect &, const прямоугольник &)

Подробнее об этом на языке программирования C++ Бьярна Страуструпа или, может быть, на этой странице: http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html

В C++ запрещено определять operator = вне класса.

alexk7 29.04.2009 18:25

Создайте промежуточный тип прокладки «RectangleEx» и определите пользовательские преобразования в / из сторонних строковых типов. Всякий раз, когда вы разговариваете с любым API, делайте это через класс оболочки.

Другой способ - получить class из rect или Rectangle и вставить туда преобразования / конструкторы.

Ответ принят как подходящий

Если вы не можете изменить структуры, у вас нет альтернативы написанию функции ручного преобразования, потому что операторы преобразования с перегрузкой работают только в теле класса. Другого пути нет.

Не уверен, насколько это разумно, но как насчет чего-то вроде этого:

class R
{
public:
    R(const rectangle& r) { ... };
    R(const Rect& r) { ... };

    operator rectangle() const { return ...; }
    operator Rect() const { return ...; }

private:
    ...
};

Затем вы можете просто обернуть каждый rectangle в R(), и все будет "правильно".

Может быть, это не так, но - в общем - наличие более одного неявного неявного преобразования может привести к двусмысленности в выражениях: предположим, что и у прямоугольника, и у Rect есть оператор &: Предположим, у вас есть R ra, rb; ra & rb; Операция & неоднозначна (может быть как прямоугольник, так и прямоугольник)

Emilio Garavaglia 19.09.2011 11:32

Другие вопросы по теме