【问题标题】:Best way to treat std::reference_wrapper<Derived> as std::reference_wrapper<Base>将 std::reference_wrapper<Derived> 视为 std::reference_wrapper<Base> 的最佳方法
【发布时间】:2020-02-09 00:45:59
【问题描述】:

我有两个类,比如“Base”和“Derived”,其中Derived 类继承Base 类。

然后是对派生类实例 (std::vector&lt; std::reference_wrapper&lt; Derived &gt; &gt; myContainer) 的引用容器。

最后,我有一个以std::vector&lt; std::reference_wrapper&lt; Base &gt; &gt; 作为参数的函数。

如果我将容器(myContainer)传递给函数,它不会编译:

如果我更改我的容器以保存对 Base 的引用,一切都会正常工作,并且因为它是一个 reference_wrapper,我相信,我仍然会有我需要的多态行为。但这感觉不干净,因为我确信我的容器不会容纳除派生实例以外的任何东西。

同时,接受向量的函数应该适用于派生类和基类。

最少的代码:

#include <vector>
#include <functional>

class Base
{ /*some virtual stuff*/ };

class Derived : public Base
{};

void Fun( std::vector< std::reference_wrapper< Base > > const & container )
{}

int main()
{
    std::vector< std::reference_wrapper< Derived > > myContainer;
    Fun( myContainer ); // Error: no viable conversion
    return 0;
}

直播代码:https://godbolt.org/z/SX5Gag

要求函数将派生引用的容器视为基本引用的向量的最佳方法是什么?

【问题讨论】:

  • 典型的解决方案是:(a) 模板化你的函数Fun;或 (b) 将“派生”向量复制到“基础”向量中。

标签: c++ stl type-conversion polymorphism reference-wrapper


【解决方案1】:

这是不可能的:

std::vector< std::reference_wrapper< Derived > > d;
std::vector< std::reference_wrapper< Base > >& b = d;

如果这是合法的,会发生什么?

SomeOtherDerivedClass o;
b.push_back(o); // sure, b is vector of Base, so legal

但 b 实际上只是对 d 的引用,所以你只是设法将一个不同的非法类型放入 d 中。

所以即使BaseDerived 的基类,同样不适用于相应的容器,无论是std::vector 还是任何其他容器。

【讨论】:

  • 糟糕。那太基础了。谢谢
  • 我猜同样的规则也适用于这种情况:godbolt.org/z/iyTzfN。对吗?
  • @sajas 嗯,这更复杂。事实上,任何两个模板实例都是不相关的类,无论这两个底层类型是否相关。但是,std::reference_wrapper 有一个非显式的强制转换运算符可供参考。这就是为什么如果您更改为... refBase(refDer);,您选择的编译器会接受!有了同样的论点,我本来希望编译器也接受你的例子,失败让我很惊讶。如果您选择最新的 clang(或最新的 GCC),则代码被接受(即使您明确选择 c++11,因此显然与标准版本无关)。
  • 请注意,虽然这种赋值或复制构造 only 是可能的,因为 cast 运算符,否则,即使使用最新的 clang,both 也会失败/GCC。
  • 因此,代码编译(在进行了您建议的更改之后),因为 reference_wrapper 有一个强制转换运算符,该运算符返回对派生类的引用,用于构造第二个包装器。没有演员,这不会发生。并且代码可以编译,而不是因为包装器是可转换的。对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-22
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 2016-03-31
  • 2020-12-23
相关资源
最近更新 更多