重载 c++类型转换(函数)

发布于 2024-11-06 11:34:03 字数 351 浏览 2 评论 0 原文

使用 C++ 风格的类型转换(全部 4 种)看起来与某些函数模板完全相同。例如

template<typename TO, typename FROM>
TO dynamic_cast (FROM p);

将被用作,

dynamic_cast<Derived*>(p); // p is Base*

为什么自定义使用的语言标准不允许重载它们? (就像我们可以重载new/delete这样的关键字或其他运算符

Using C++ style typecastings (all 4) look exactly like some function template. e.g.

template<typename TO, typename FROM>
TO dynamic_cast (FROM p);

will be used as,

dynamic_cast<Derived*>(p); // p is Base*

Why is it not allowed to overload them by language standard for custom usage ? (like we can overload the keywords like new/delete or other operators)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

但可醉心 2024-11-13 11:34:03

为什么自定义使用的语言标准不允许重载它们

我想这是因为标准委员会在介绍这些时,认为所有这四种类型转换的语义都定义良好,并且适用于它们应该是的所有类型。大多数情况下,这是真的。

我所知道的唯一反例是无法在智能指针实例之间进行dynamic_cast

shared_ptr<Derived> pd = dynamic_cast<shared_ptr<Derived> >(pb);

我认为这样做的能力会有一些优点。

我不知道在标准委员会中完成所有工作的志愿者是否已经讨论过这个问题(而且我懒得去谷歌),但是如果已经讨论过(我想是这样),那么它已经被讨论过。被拒绝要么是因为有人认为弊大于利,要么是因为没有人有时间提出一个体面的建议并引导其通过。1


1别笑。实际上,有很多事情大多数人都认为拥有是件好事,但这些事情之所以未能实现,是因为没有人愿意费心去写一份像样的提案,花时间讨论和迭代改进它,直到它能够实现。可以进行投票。

Why is it not allowed to overload them by language standard for custom usage?

I suppose that's because the standard committee, when introducing these, thought the semantics of all four of these casts are well defined, and applicable to all types they should be. And mostly, this is true.

The only counter example I know of is the inability to dynamic_cast between smart pointer instances:

shared_ptr<Derived> pd = dynamic_cast<shared_ptr<Derived> >(pb);

I suppose the ability to do that would have some merits.

I don't know whether this has been discussed by the volunteers that did all the work in the standards committee (and I'm too lazy to google), but if it has been discussed (and I'd think so), it's been rejected either because someone thought the disadvantages outweigh the advantages, or because nobody had found the time to make a decent proposal and shepherd it through.1


1 Don't laugh. There's actually a lot of things most agree would be nice to have, and which are only failing to materialize because nobody could be bothered to do the work of writing a decent proposal, and spending the time needed to discuss and to iteratively improve it until it can be voted on.

依 靠 2024-11-13 11:34:03

我认为原因是相同的,因为你不能重载语言关键字。

事实上,您必须将它们视为语言关键字而不是模板函数,即使看起来相同。 OTOH,我无法想象通过改变这个特定的 C++ 方面的含义会造成什么样的灾难。

编辑
我很确定有人会提出这样的问题:“那为什么你可以重载new/delete?”。我认为在某些情况下您需要内存分配/释放自定义,并且允许您超载它们的好处超过了风险。我看不出颠覆 C++ 类型系统有任何优势,我无法想象它会有用的场景。你?

I think the reason is the same for you can't overload language keyword.

In fact, you have to see them as language keyword and not template function, even if the look the same. OTOH, I couldn' imagine what kind of disasters one could do by changing the meaning of this particular C++ aspect.

EDIT
I was pretty sure that someone would have come up with the question: "then why you can overload new/delete?". I think that memory allocation/deallocation customization is something that you need in certain scenarios, and the benefits of allowing you to overload them outweighs the risks. I can't see any advantage in subverting the C++ type system, IOW I fail to think a scenario where it would be useful. Do you?

眼波传意 2024-11-13 11:34:03

使用 dynamic_castreinterpret_caststatic_cast 进行指针转换具有明确定义的含义,最好不要允许重载。
允许用户更改 const_cast 的含义将是一件痛苦的事情。

仅保留对象类型转换。

struct A
{
  A() {};
  template <typename FROM>
  A(FROM&)  {
    std::cout << "Casting to A \\o/" << std::endl;
  }

  template <typename TO>
  operator TO()  {
    std::cout << "Casting from A \\o/" << std::endl;
    return TO();
  }
};

那么

  int i; A a;
  A toA = static_cast<A>(i);  //  Casting to A \o/
  int fromA = static_cast<int>(a); // Casting from A \o/

希望你有比我更好的用例:)

Pointer conversion with dynamic_cast, reinterpret_cast and static_cast have well defined meanings and it is probably better not to allow overloading.
It would be a pain to allow users to change the meaning of const_cast.

Only object type casting remains.

struct A
{
  A() {};
  template <typename FROM>
  A(FROM&)  {
    std::cout << "Casting to A \\o/" << std::endl;
  }

  template <typename TO>
  operator TO()  {
    std::cout << "Casting from A \\o/" << std::endl;
    return TO();
  }
};

then

  int i; A a;
  A toA = static_cast<A>(i);  //  Casting to A \o/
  int fromA = static_cast<int>(a); // Casting from A \o/

Hopefully you have better use cases than mine :)

筱武穆 2024-11-13 11:34:03

您不能重载这些运算符。
可以说,这是因为你无法改变其他答案所说的这样一个基本事物的含义。 (就像更改整数的 + 的含义,或更改 * 装饰以从类型生成指针一样)。

话虽如此,没有什么可以阻止您定义自己的强制转换函数的概括,这些函数接受一个参数并返回与其密切相关的内容。
实际上,我认为相反的观点是,你永远不应该使用语言转换操作(static/dynamic/reinterpret_cast),除非你正在做相当低级的事情。

您想要做的可能是定义自己的转换函数,大多数时候其行为类似于语言提供的函数,但偶尔它们会为您的特定目的执行更具体的操作。您必须认真思考这个函数真正的用途,并为它命名。你能承受什么样的运行时成本,“失败”时什么样的行为(抛出异常?,返回空值?)等等。

标准和许多库都充满了这样的函数。有时他们会在语言演员表上添加一些调整后的行为,有时他们会做得更多。
一些示例:

https://en.cppreference.com/w/cpp/memory /shared_ptr/pointer_cast

  • std::static_pointer_cast,
  • std::dynamic_pointer_cast,
  • std::const_pointer_cast,
  • std::reinterpret_pointer_cast

  • std::any_cast

  • std::chrono::time_point_cast

(另请参阅https://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/pointer_cast.html)

https://www.boost.org/doc/libs/1_42_0/libs/conversion/lexical_cast.htm

  • boost ::lexical_cast

https://www.boost .org/doc/libs/1_63_0/libs/conversion/cast.htm

  • polymorphic_cast
  • polymorphic_downcast
  • polymorphic_pointer_cast
  • polymorphic_pointer_downcast

https: //www.boost.org/doc/libs/1_72_0/libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html

  • boost::numeric_cast

https://www.boost.org/doc/ libs/1_47_0/doc/html/boost_units/Quantities.html#boost_units.Quantities.Quantity_Construction_and_Conversion

  • boost::units::quantity_cast

有时它们根本不被称为 cast :)

https ://en.cppreference.com/w/cpp/utility/variant/get_if

  • std::get_if

另一个例子,对于模板代码,我编写了这个强制转换函数,只有当转换可以隐式完成:

    template<class To, class From, std::enable_if_t<std::is_convertible<From, To>{}, int> =0>
    To implicit_cast(From&& f){
        return static_cast<To>(f);
    }

https://godbolt.org/z/ym8MnJ

You cannot overload these operators.
It is, arguably, because you cannot change the meaning of such a fundamental thing as other answers say. (Like changing the meaning for + for integers, or the * decoration to generate a pointer from a type).

Having said that, nothing prevents you from defining your own generalizations of cast functions, that take an argument and return things very related to it.
Actually, I would argue the opposite point of view, you should never use the language cast operations (static/dynamic/reinterpret_cast) unless you are doing pretty low level stuff.

What you would want to do probably is to define your own casting function that most of the time behaves like the ones provided by the language but once in a while they do something more specific for your specific purposes. You have to think hard what this function really does and name it well. What kind of runtime cost you can afford, what kind of behavior on "failure" (throw execption?, return a null value?), etc.

The standard and many libraries are full of such functions. Sometimes they add a tweaked behavior over language cast, other times they do more.
Some examples:

https://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast

  • std::static_pointer_cast,
  • std::dynamic_pointer_cast,
  • std::const_pointer_cast,
  • std::reinterpret_pointer_cast

  • std::any_cast

  • std::chrono::time_point_cast

(see also https://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/pointer_cast.html)

https://www.boost.org/doc/libs/1_42_0/libs/conversion/lexical_cast.htm

  • boost::lexical_cast

https://www.boost.org/doc/libs/1_63_0/libs/conversion/cast.htm

  • polymorphic_cast,
  • polymorphic_downcast,
  • polymorphic_pointer_cast
  • polymorphic_pointer_downcast

https://www.boost.org/doc/libs/1_72_0/libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html

  • boost::numeric_cast

https://www.boost.org/doc/libs/1_47_0/doc/html/boost_units/Quantities.html#boost_units.Quantities.Quantity_Construction_and_Conversion

  • boost::units::quanity_cast.

Sometimes they are not called cast at all :)

https://en.cppreference.com/w/cpp/utility/variant/get_if

  • std::get_if

Another example, for template code I wrote this cast function that is only invoked if the conversion can be done implicitly:

    template<class To, class From, std::enable_if_t<std::is_convertible<From, To>{}, int> =0>
    To implicit_cast(From&& f){
        return static_cast<To>(f);
    }

https://godbolt.org/z/ym8MnJ

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文