【问题标题】:std::bind on operator[] of std::arraystd::bind 在 std::array 的 operator[] 上
【发布时间】:2023-04-01 21:40:01
【问题描述】:

我试图在 std::array 的 or operator[] 处绑定一个成员函数,但编译器 (gcc 7.3) 说它无法确定类型名 _Func。所以我创建了自己的结构数组来看看问题出在哪里。但在这种情况下它可以正常工作。

#include <iostream>
#include <functional>
#include <array>

template<typename ret, unsigned int size>
struct my_arr {
    ret data[size];

    ret& at(unsigned int i) {return data[i];}

    ret& operator[](unsigned int i){return data[i];}
};

using namespace std::placeholders;
using namespace std;

int main() {

    my_arr<int,3> ma = {1,2,3};

    auto x = std::bind(&my_arr<int,3>::at, _1, 0); // ok

    auto x1 = std::bind(&my_arr<int,3>::operator[], _1, 0); // ok

    auto arr_x = std::bind(&array<double, 3>::at, _1, _2); // error

    auto arr_x = std::bind(&array<double, 3>::operator[], _1, _2); // error

    std::cout << x(ma) << std::endl << x1(ma) << std::endl;

}

编译错误是:

没有匹配函数调用'bind(, const std::_Placeholder&, const std::_Placeholder&)' 自动 arr_x = std::bind(&array::at, _1, _2); ^


我已经意识到是什么导致了这个错误,但我仍然不知道如何解决它。问题是编译器不知道我指的是哪个函数,因为这些函数有 const 和非 const 变体。此代码模拟相同的错误。
#include <iostream>
#include <functional>
#include <array>

template<typename ret, unsigned int size>
struct my_arr {
    ret data[size];

    ret& at(unsigned int i) {return data[i];}
    const ret& at(unsigned int i) const {return data[i];}
    ret& operator[](unsigned int i){return data[i];}
};

using namespace std::placeholders;
using namespace std;

int main() {

    my_arr<int,3> ma = {1,2,3};

    auto x = std::bind(&my_arr<int,3>::at, _1, 0); // error

    auto x1 = std::bind(&my_arr<int,3>::operator[], _1, 0); // ok

    std::cout << x(ma) << std::endl << x1(ma) << std::endl;

}

我还是不知道怎么指定要调用哪个版本的函数,如何绑定const版本和非const版本?

【问题讨论】:

  • Fwiw,只需使用 lambda:auto foo = [&amp;ma](auto some_param){ return ma[some_param]; };
  • 您可能知道这一点,但让我指出operator[] 和at 并不等同。 at 执行边界检查,因此更安全,效率更低。
  • @Tom 我已经写了答案,所以请看一下它并给它一个赞成票和/或接受它(投票下方的绿色勾号)如果它对你有帮助

标签: c++ c++11 constants bind function-reference


【解决方案1】:

因为你有两个重载:

  • ret&amp; at(unsigned int i) 和
  • const ret&amp; at(unsigned int i) const

编译器不知道你真正想绑定哪个函数重载。因此,您需要将函数指针强制转换为确切的函数签名。

这可行:

auto x = std::bind(static_cast<int&(my_arr<int, 3>::*)(unsigned int)>(&my_arr<int,3>::at), _1, 0);

看看live

您还可以使用 lambdas 以更优雅的方式解决您的问题:

auto x2 = [&ma](auto const p) { return ma.at(p); };
std::cout << x2(0) << std::endl; // output: 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    相关资源
    最近更新 更多