C++ 重载类型转换以使类与指针行为相同时的正确行为
我希望类的行为与指针相同,但也支持比较运算符,如C++ 重载类型转换以使类与指针行为相同时的正确行为,c++,casting,operator-overloading,C++,Casting,Operator Overloading,我希望类的行为与指针相同,但也支持比较运算符,如 我遇到了铸造问题: ptr_t<foo> x = new foo; (bar*)x; // cast should be allowed static_cast<bar*>(x); // cast should fail 如果我在定义中使用C样式,则静态\u cast变得不安全。如果我使用static\u cast,那么C样式就没有那么有用了。如何解决此问题?您可以通过重载箭头和取消引用操作符,
我遇到了铸造问题:
ptr_t<foo> x = new foo;
(bar*)x; // cast should be allowed
static_cast<bar*>(x); // cast should fail
如果我在定义中使用C样式,则
静态\u cast
变得不安全。如果我使用static\u cast
,那么C样式就没有那么有用了。如何解决此问题?您可以通过重载箭头和取消引用操作符,同时提供get
功能,轻松模拟ptr\t
的行为,就像foo*
。这就是所有智能指针的操作方式(按照惯例),使用它更自然。随意摆弄石膏似乎是不必要的复杂和脆弱
template <typename T>
struct ptr_t
{
T* get() const;
T* operator->() const
{
return get();
}
T& operator*() const
{
return *get();
}
};
模板
结构ptr\t
{
T*get()常量;
T*运算符->()常量
{
返回get();
}
T&运算符*()常数
{
return*get();
}
};
structfoo
{
无效条()常数;
};
void baz(foo*);
ptr_t x=/*…*/;
x->bar();
(*x.bar();
baz(x.get());
这并不能解决我自己的问题,但我意识到这可能对未来的观众有所帮助:
template<typename t>
using ptr_t = t*;
模板
使用ptr_t=t*;
这将导致ptr\u t
的行为与foo*
相同(技术上是相同的类型)
不幸的是,我需要重载
,使其与常规指针不同,因此在我的情况下,这不起作用
我想让一个类的行为与指针相同,但是
您的要求显然无法满足:
如果它的行为类似于指针,那么它就是指针。
因此,它不是一个类,不能定义重载等
令人惊讶的是,如果用其他类型的指针替换,这是一个常见的问题。为什么希望
静态\u cast
失败?这对我来说毫无意义。@R.MartinhoFernandesptr
应该具有与foo*
相同的行为foo
和bar
是不相关的类。我认为你不能告诉编译器为了好玩而将ptr\u t
精确匹配到foo*
,你需要让C风格的cast为你做一个重新解释cast
,而不需要转换操作符(这将使静态\u cast
工作)。请注意,转换在示例中并不是隐含的。@R.MartinhoFernandes:我会被诅咒的,我习惯于忽略这一点。这是有效的,尽管他们的行为不同。我需要能够在模板中同时使用指针和ptr\t。@Pubby:你的问题并没有这样说@Pubby:从来没有一个类对指针的行为是相同的。你的问题没有意义。如果您有一些特定的域,其中应用了特定的约束,那么您可以模拟它,但是类根本不是指针,您需要接受它。嘿!那是我的哑巴!(值得一提的是,这将导致ptr_t
成为foo*
。这是一个别名,不是一个新类型。除了具有不同的语法,它是相同的)相关的:这不会“导致ptr_t
与foo*
行为相同”;这使得两者实际上是同一类型。听起来我可能有点迂腐,但事实上,这微妙地使整个答案与任何事情都毫不相干。@TomalakGeret'kal说得很好。我同意这不是一个非常有用的答案,我可能会删除它。std::less
定义了一个总的顺序,即使+1,因为它是对您的需求“行为与指针相同”的唯一正确答案。你必须明白你的问题毫无意义。
struct foo
{
void bar() const;
};
void baz(foo*);
ptr_t<foo> x = /* .. */;
x->bar();
(*x).bar();
baz(x.get());
template<typename t>
using ptr_t = t*;