【问题标题】:Proper behavior when overloading casts to have class behave identically to pointers重载强制转换以使类的行为与指针相同时的正确行为
【发布时间】:2011-12-02 03:51:28
【问题描述】:

我想让一个类的行为与指针相同,也支持比较运算符,如<>

我遇到了铸造麻烦:

ptr_t<foo> x = new foo;
(bar*)x;              // cast should be allowed
static_cast<bar*>(x); // cast should fail

上面的 sn-p 应该表现得好像 ptr_t&lt;foo&gt;foo*

这里是强制转换运算符:

template <typename cast_t>
explicit inline operator cast_t() {
  return (cast_t)(ptr); // causes static_cast to use C-style, which is bad
}

如果我在定义中使用 C 风格,那么 static_cast 就会变得不安全。如果我使用static_cast,那么 C 风格就变得没那么有用了。我该如何解决这个问题?

【问题讨论】:

  • 您为什么希望static_cast 失败?这对我来说毫无意义。
  • @R.MartinhoFernandes ptr&lt;foo&gt; 应该具有与foo* 相同的行为。 foobar 是不相关的类。
  • 我不认为你可以告诉编译器将 ptr_t&lt;foo&gt;foo* 完全匹配以获得乐趣,并且你需要让 C 风格的演员做一个 reinterpret_cast对你来说,没有转换运算符(这将使static_cast 工作)。

标签: c++ casting operator-overloading


【解决方案1】:

您可以通过重载箭头和取消引用运算符轻松模拟 ptr_t&lt;foo&gt; 的行为,就像 foo* 一样,同时提供 get 函数。这就是所有智能指针的操作方式(按照惯例),并且使用起来更加自然。摆弄演员阵容似乎不必要地复杂和脆弱。

template <typename T>
struct ptr_t
{
    T* get() const;

    T* operator->() const
    {
        return get();
    }

    T& operator*() const
    {
        return *get();
    }
};

struct foo
{
    void bar() const;
};

void baz(foo*);

ptr_t<foo> x = /* .. */;

x->bar();
(*x).bar();
baz(x.get());

【讨论】:

  • 请注意,示例中没有隐式转换。
  • @R.MartinhoFernandes:我会被诅咒的,我已经习惯了忽略这一点。
  • 这行得通,尽管它们的行为不一样。我需要能够在模板中同时使用指针和 ptr_t。
  • @Pubby:你的问题没有说明任何问题。 Perhaps you should describe your goal, not the step.
  • @Pubby:没有任何类的行为会与指针完全相同。你的问题没有实际意义。如果你有一些特定的域应用了特定的约束,你可以模拟它,但是一个类根本不是一个指针,你需要接受它。
【解决方案2】:

这不是我自己问题的解决方案,但我意识到这可能对未来的观众有所帮助:

template<typename t>
using ptr_t = t*;

这将导致ptr_t&lt;foo&gt; 的行为与foo* 相同(从技术上讲,它是同一类型)

不幸的是,我需要重载 &lt;&gt; 以不同于常规指针,因此这在我的情况下不起作用。

【讨论】:

  • 嘿!那是我的dumb_ptr! (为了什么有价值,这将导致ptr_t&lt;foo&gt; 成为 foo*。这是一个别名而不是一个新类型。除了语法不同,它是相同的)相关:chat.stackoverflow.com/rooms/10/conversation/dumb-ptr跨度>
  • 这不会“导致ptr_t&lt;foo&gt; 的行为与foo* 相同”;它使两者实际上是同一类型。听起来我很迂腐,但实际上这巧妙地使整个答案与任何事情都完全无关。
  • @TomalakGeret'kal 好点。我同意这不是一个非常有用的答案,我可能会删除它。
  • std::less&lt;T*&gt; 定义了总订单,即使 &lt; 没有。那能解决你的问题吗?也许您可以解释为什么要进行比较。
  • +1,因为它是唯一满足您“行为与指针相同”要求的正确答案。你必须明白你的问题是没有意义的。
【解决方案3】:

我想让一个类的行为与指针相同,但是

您的要求显然无法满足:

如果它表现得像一个指针,它就是一个指针。

所以,它不是一个类,你不能定义重载等等。

令人惊讶的是,如果您用其他类型代替“指针”,这是一个常见问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    相关资源
    最近更新 更多