为什么C ++中的类型可转换性不可传递?

问题描述 投票:2回答:2

请考虑以下静态断言:

    static_assert(std::is_convertible_v<int const&, int const>);
    static_assert(std::is_convertible_v<int const, int>);
    static_assert(std::is_convertible_v<int, int &&>);

    static_assert(std::is_convertible_v<int const&, int &&>);

以上三个断言通过,但最后一个断言失败。

这意味着C ++中的类型可转换性一般不具有传递性,我认为这是非常违反直觉的。

我搜索了标准和cppreference网站,找到任何证据表明这是预期的行为,但到目前为止我还没有成功。

有趣的是,对于左值引用,一切都很好,因为std::is_convertible_v<int, int&>是假的。我也希望rvalue-references。

我认为它与如何定义is_convertible有关。在定义中,To参数显示为虚函数的返回类型。根据我的理解,任何类型的新值都是临时的,因此可以转换为右值引用。因此std::is_convertible_v<T, T&&>适用于任何类型的T

更具体地说,我提出以下问题:

  1. is_convertible真的抓住了可兑换的直觉吗?
  2. 如果没有,它还捕获了什么?或者措辞不同:我对可兑换的直觉不合适吗?
  3. 如果我们将is_convertible理解为二元关系,那么它不应该是预订,即传递吗?为什么不?

直观地说,imho,convertiblity应该意味着:只要需要类型To,你也可以使用类型From。这意味着传递性。

特别是,T不应该转换为T&&,因为你不能使用需要TT&&(你可能不会从T移动,但你可能会从T&&移动)。

我在这里遇到了严重的错误吗?

c++ type-conversion typetraits type-systems
2个回答
3
投票

直观地说,imho,convertiblity应该意味着:只要需要类型To,你也可以使用类型From ....

这就是它的意思。

......这意味着传递性。

不,这不正确。并非每个二元关系都必须是可传递的。来自cppreferene的隐式转换:

隐式转换序列按以下顺序包含以下内容:

1)零个或一个标准转换序列;

2)零或一个用户定义的转换;

3)零个或一个标准转换序列。

在考虑构造函数或用户定义的转换函数的参数时,只允许一个标准转换序列(否则可以有效地链接用户定义的转换)。从一种内置类型转换为另一种内置类型时,只允许一个标准转换序列。

确切的规则是相关的,但考虑“零或一个用户定义的转换;”因此,当你有用户定义的从FooBar以及从BarBaz的转换时,这并不一定意味着Foo转换为Baz

它不是std::is_convertible有一个奇怪的可转换概念,但C ++中有关可兑换的规则从一开始就不具有传递性。


1
投票

这意味着C ++中的类型可转换性一般不具有传递性,我认为这是非常违反直觉的。

一般来说,你不想将const T&转换为T&&。这可能会带来灾难性的后果。你想要一个编译器错误,这样你就不会意外地从调用者那里获取调用者的数据(或者,创建一个看似没有复制的非预期副本)


现在,标准对此有何看法? std::move

标准转换序列是一系列标准转换,顺序如下: - 来自以下集合的零或一次转换:左值到右值的转换,数组到指针的转换以及函数到指针的转换。 - 来自以下集合的零或一次转换:整数促销,浮点促销,积分转换,浮点转换,浮点积分转换,指针转换,指针到成员转换和布尔转换。 - 零或一个函数指针转换。 - 零或一个资格转换。

因此,我们可以通过[conv]隐式地将int const&转换为int(在非类型类型上它会删除cv资格)。

我们还可以通过Identity转换隐式地将lvalue-to-rvalue conversion转换为int(不需要转换,因为我们可以执行prvalue与rvalue引用的引用绑定)。

但我们不能隐含地将int&&转换为int const&,因为这需要

  • 左值转换左值(Lvalue Transformation),int&&int const&,然后是
  • 身份转换(参考绑定),intint

这是因为我们不能以这种方式将身份转换与其他转换混合,根据int const&

标准转换序列要么是身份转换本身(即没有转换),要么包含来自其他四个类别的一到三次转换。

(由[over.ics.scs]定义的类别)

© www.soinside.com 2019 - 2024. All rights reserved.