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

时间:2011-05-12 07:57:19

标签: c++ casting overloading

使用C ++样式的类型转换(全部4个)看起来与某些功能模板完全相同。 e.g。

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

将用作,

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

为什么不允许按自定义使用的语言标准超载? (比如我们可以重载关键字,例如new/delete或其他operators

4 个答案:

答案 0 :(得分:4)

  

为什么不允许超载按语言标准进行自定义使用?

我认为这是因为标准委员会在介绍这些时,认为所有这四个演员的语义都已明确定义,并适用于他们应该的所有类型。而且大多数情况下都是如此。

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

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

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

我不知道在标准委员会做过所有工作的志愿者是否已经讨论过这个问题(而且我对谷歌太懒了),但是如果已经讨论过了(我会这么认为)它被拒绝了,因为有人认为这些缺点超过了优势,或者是因为没有人找到时间提出一个好的建议并且通过它。 1


1 不要笑。实际上有很多事情是大多数人都认为很好的事情,而这些事情只是没有实现,因为没有人会为编写一份体面的提案而花费时间,并花费时间讨论并反复改进它直到它可以投票。

答案 1 :(得分:2)

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

事实上,您必须将它们视为语言关键字,而不是模板功能,即使外观相同。 OTOH,我无法想象通过改变这个特定C ++方面的含义可以做些什么样的灾难。

修改
我很确定有人会提出这个问题:“那么为什么你可以重载new / delete?”。我认为内存分配/解除分配定制是某些情况下您需要的东西,允许您超载它们的好处超过了风险。我无法看到颠覆C ++类型系统的任何优势,IOW我没有想到它会有用的场景。你呢?

答案 2 :(得分:1)

使用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/

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

答案 3 :(得分:0)

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

话虽如此,但没有什么可以阻止您定义自己的类型转换函数的概括,这些泛型函数接受一个参数并返回与其非常相关的东西。 实际上,我会提出相反的观点,除非您做的是底层工作,否则永远不要使用语言转换操作(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::quanity_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