将std::shared_ptr隐式转换为指针类型

3
我有一些包装类,用于封装C库,比如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_Texture *为参数的SDL函数,我希望我的texture_ttexture_ptr_t可以隐式转换为它。
我尝试在我的类中实现这些运算符:
operator SDL_Texture *(void);
operator const SDL_Texture *(void) const;

但我仍然会收到“texture_ptr_t到SDL_Texture *的转换不可行”的错误。有人能指点我如何正确解决吗?

你无法控制转换的两个部分。std::shared_ptr 没有办法转换为原始指针,而 SDL_Texture 也没有办法从这样的指针构造对象。 - Hatted Rooster
2
您可以像使用裸指针一样对shared_ptr进行取消引用,这不足以满足您的需求吗?请提供[minimal, complete, and verifiable example]。 - rustyx
@curiousguy 你可以搜索一下为什么智能指针不提供到它们管理的指针类型的隐式转换,以找出为什么这是一个不好的想法。 - Nikos C.
@NikosC。如果程序员不知道自己在做什么,那就是个坏主意...对于所有事情都是如此。C++标准库过于守护和保护,同时使用浮点数等东西时难以正确使用。 - curiousguy
2
@curiousguy,这不是关于知道你在做什么的问题。而是关于犯错误,编译器没有捕捉到它们,因为你劫持了类型安全系统。 - Nikos C.
显示剩余6条评论
2个回答

2
你即使使用原始指针,也会得到这些错误,因此我将暂时放弃使用 shared_ptr。
隐式转换仅适用于 texture_t 对象,而不是指向它的指针(智能或其他)。它无法工作,因为 shared_ptr 和 dumb pointer 都没有将其转换为不相关指针类型。
因此,要调用任何 SDL_func 并启动转换,您需要提供对 texture_t 的 glvalue(引用)。这很容易通过解引用实现。
SDL_func(*ptr, /* other args */); // ptr can be a dumb pointer too.

但是,说了这么多,这感觉像是一个泄漏的抽象。如果你已经尝试包装SDL_Texture*,那么不要止步于半成品。让texture_t成为一个完全值语义类型,提供对SDL库的抽象操作。不要让调用代码知道你使用了哪个库。这将使以后需要切换库更加容易。


0

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>......也许这不是问题,或者将来可能会引起问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接