绑定纯虚方法

问题描述 投票:0回答:1

假设我们有以下层次结构:

class Add3Interface {
  virtual int add3 (const int&) const = 0;
};

class Add3: public Add3Interface {
  virtual int add3 (const int& arg) const override {
    return arg + 3;
  }
};

我想绑定

add3
方法,这样我就可以在
std::views::transform
之类的事情中使用它。 下面的代码就可以了:

const Add3 myAdder{};
const auto myFun = std::bind(&Add3::add3, myAdder, std::placeholder::_1);

但是,在我的用例中,我无权访问具体类型,因此我必须编写如下内容:

const Add3Interface& myAdder = Add3{};
const auto myFun = std::bind(&Add3Interface::add3, myAdder, std::placeholder::_1);

然而,这让编译器感到不安:

/usr/include/c++/11/tuple:238:13: error: cannot declare field ‘std::_Head_base<0, Add3Interface, false>::_M_head_impl’ to be of abstract type ‘Add3Interface’

如何绑定对象的方法?

我希望像

typeid
这样的东西可能会有所帮助:

const auto myFun = std::bind(&(typeid(myAdder)::add3), myAdder, std::placeholders::_1);

但这只会导致各种语法错误,具体取决于我如何放置各种括号。

当然我们可以只使用 lambda:

const auto myFun = [&myAdder] (const auto& arg) { return myAdder.add3(arg); };

但如果可能的话,我更愿意使用

bind
,因为我觉得它代表了我从语义角度试图做得更好的事情。

c++ pure-virtual stdbind
1个回答
0
投票

std::bind
尝试存储其所有参数按值。在本例中,它尝试将
myAdder
复制到
Add3Interface
类型的数据成员中。当然,由于
Add3Interface
是抽象的,所以这是失败的。问题不在于成员函数指针的类型错误。

如果您希望

std::bind
通过引用引用存储的参数,请传递
std::reference_wrapper<T>
而不是
T
。您可以使用便利函数
std::ref
std::cref
来构造
std::reference_wrapper
s。

Add3Interface const &myAdder = Add3{};
auto const myFun = std::bind(&Add3Interface::add3, std::ref(myAdder), std::placeholders::_1);

(准确地说,

std::bind
本身根本不专门处理
std::reference_wrapper
。它只会将
std::reference_wrapper
的副本存储为数据成员,就像存储任何其他参数的副本一样。调用存储函数之前的
std::reference_wrapper
来自标准
INVOKE
操作(本质上是
std::invoke
),
std::bind
和其他标准实用程序将“调用可调用”的工作委托给该操作。)

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