Неявное преобразование std :: shared_ptr в тип указателя - PullRequest
3 голосов
/ 11 мая 2019

У меня есть классы-обертки, которые обернуты в C Libary. В этом случае SDL. Я сокращу все до необходимых деталей, если что-то не хватает, пожалуйста, сообщите мне в комментариях.

Так, например, у меня есть класс с именем texture_t, который обернет SDL_Texture

class texture_t
{
public:
...
private:
    SDL_Texture *tex;
}

Иногда это может быть shared_ptr:

typedef std::shared_ptr<texture_t> texture_ptr_t;

Теперь, если я хочу вызвать SDL функцию, которая принимает SDL_Texture * в качестве аргумента, я хочу, чтобы мои texture_t и texture_ptr_t неявно преобразовались в нее.

Я пытался реализовать эти операторы в своем классе:

operator SDL_Texture *(void);
operator const SDL_Texture *(void) const;

Но я все еще получаю no viable conversion from texture_ptr_t to SDL_Texture * ошибок. Может кто-нибудь указать мне правильное направление для получения этого права?

Ответы [ 2 ]

2 голосов
/ 11 мая 2019

Вы получите эти ошибки даже при отсутствии shared_ptr с необработанным указателем, поэтому я на мгновение откажусь от него.

Неявное преобразование применимо только с texture_t объект , а не из указателя на один (умный или другой).Это не работает, потому что ни shared_ptr, ни тупой указатель не имеют этого преобразования в несвязанный тип указателя.

Так что, чтобы вызвать любой SDL_func и получить переходное значение, вам нужно предоставить glvalue(ссылка) на texture_t.Это легко сделать с опровержением.

SDL_func(*ptr, /* other args */); // ptr can be a dumb pointer too.

Но, сказав все это, это похоже на дырявую абстракцию.Если вы приложили усилие, чтобы обернуть SDL_Texture*, не останавливайтесь на полумере.Имейте texture_t полностью семантический тип значения, который обеспечивает абстрактные операции над библиотекой SDL.Не обременяйте код вызова информацией о том, какую библиотеку вы используетеВ дальнейшем вам будет проще переключать библиотеки, если это потребуется.

0 голосов
/ 11 мая 2019

C ++ неявное преобразование дает власть кодеру.С помощью одного оператора преобразования можно значительно расширить интерфейс класса.Это то, что вы хотите сделать, и я думаю, что это хорошая идея.

Но вы должны знать, что неявные преобразования приводят к быстрому росту сложности кода.Красота возникает из-за сложности, но хаос никогда не бывает далеко.Итак, мы должны научиться справляться со зверем!Итак, попрактикуемся.

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

Таким образом, вы должны объявить оператор преобразования из shared_ptr<texture_t>, но это невозможно, потому что операторы преобразования должны бытьфункции-члены.Таким образом, один из вариантов может быть производным от shared_ptr:

class texture_ptr_t
  :public std::shared_ptr<texture_t> {

  operator SDL_texture*() const{
    return *get();
    }
  };

Теперь вам нужно тщательно спроектировать этот класс, этот неявно конвертируется в shared_ptr<texture_t> через преобразование из производного в базовое ... Может быть, этоне проблема или, может быть, это вызовет проблемы позже.

...