为啥使用与父级一起声明的 std::function 在与子级一起使用时会显示错误?

Posted

技术标签:

【中文标题】为啥使用与父级一起声明的 std::function 在与子级一起使用时会显示错误?【英文标题】:Why does using a std::function declared with the parent show me an error when used with a child?为什么使用与父级一起声明的 std::function 在与子级一起使用时会显示错误? 【发布时间】:2019-12-09 14:39:08 【问题描述】:

这是位于接口中的虚拟排序函数的声明,使用 std::function。

using Comparefunction = std::function<bool(const DataHandling::GridDataStruct &d1, const 
DataHandling::GridDataStruct  &d2)>;

virtual bool Sort(const Comparefunction& fct);

这是 std::function 所寻址的函数:

bool operator() (const Types::Order &d1, const Types::Order &d2)const;

其中 Types::Order 是 GridDataStruct 的子级。

在实例化包含上述运算符的类时使用 std::function:

 Sort(Tools::OrderComparer(grid, false));

->OrderComparer 包含上面显示的运算符

-> 顶部也提到了排序。

如果有任何问题或不清楚的地方,请随时提出!

简化的错误信息:

没有合适的用户定义的从(包含运算符的类)到(std::function 寻址运算符)的转换

【问题讨论】:

这是给你的minimal reproducible example(通常你应该自己创建):godbolt.org/z/PcA5zJ 因此,如果编译器允许您尝试执行的操作,那么如果代码的其他部分调用您的 Comparefunction 并带有 GridDataStruct 的子代 not,您会期望发生什么Types::Order 类型的?简单来说,你的代码说Sort 想要一个CarComparer,但你只给它一个PorscheComparer。编译器对此不满意是完全正确的——如果有人使用CarComparer 比较两个Mercedes 实例怎么办? 你说得有道理。我还真没想到。 我不知道您的方法是否错误,问题包含的信息太少,无法判断(这很好,原始问题不那么广泛)。但是进一步考虑这一点应该会导致您的设计中出现某种不合逻辑的接缝或边缘情况。也许您可以将Sort(或整个界面)作为模板而不是运行时多态性? 已经是模板了,但是Type用于其他抽象函数的声明。所以我不得不转而采用不同的方法。无论如何非常感谢你,我感谢你的帮助! 【参考方案1】:

这归结为

struct Base  virtual ~Base(); ;

struct Derived : Base ;

struct Comparer

    bool operator()(const Derived&, const Derived&)
    
        return true;
    
;

std::function<bool(const Base&, const Base&)> comp(Comparer);

https://godbolt.org/z/_7Xtfn

comp 应该能够比较两个Base 实例。但是Comparer只能比较Derived实例,所以不能用来初始化comp

或者,重复上面的评论:代码说“Sort想要一个CarComparer”但你只给它一个PorscheComparer。编译器对此不满意是完全正确的 - 如果有人使用 CarComparer 比较两个 Mercedes 实例怎么办?

也许PorscheComparer 只会用于比较Porsche 实例。表达这一点的简洁方法是在具体汽车类型上模板 Sort(或整个接口) - 可能完全消除继承层次结构(用编译时多态性替换它)。

【讨论】:

【参考方案2】:

您正在展示一个接口,该接口可以接受来自DataHandling::GridDataStruct 的任何内容中的两个。

但是,实际的实现只能取两个Types::Orders,一个更具体、更派生的类。

我认为你的期望倒退了。

【讨论】:

以上是关于为啥使用与父级一起声明的 std::function 在与子级一起使用时会显示错误?的主要内容,如果未能解决你的问题,请参考以下文章

RelativeLayout 中的 ImageView 与父级不匹配

使 QMenu 具有与父级相同的宽度(QPushButton)

卡片宽度与父级匹配:颤动

css 下拉菜单与父级相同的宽度

FrameLayout 高度与父级不匹配

present Modal View Controller:如何与父级交互