std :: bind для оператора [] из std :: array - PullRequest
2 голосов
/ 25 января 2020

Я пытаюсь привязать функцию-член к или оператору [] из std :: array, но компилятор (g cc 7.3) говорит, что не может определить имя типа _Fun c. Поэтому я создал свой собственный массив struct, чтобы увидеть, в чем проблема. Но в этом случае работает fin.

#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 <1> & , const std :: _ Placeholder <2> &) 'auto arr_x = std :: bind (& array :: at, _1, _2); ^

Я понял, что вызывает эту ошибку, но я все еще не знаю, как ее решить. Проблема в том, что компилятор не знает, к какой функции я обращаюсь, потому что есть постоянные и неконстантные варианты этих функций. Этот код симулирует ту же ошибку.

#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;

}

Я до сих пор не знаю, как указать, какую версию функции я хочу вызвать, как связать версию с константой и версию без констант?

1 Ответ

3 голосов
/ 25 января 2020

Поскольку у вас есть две перегрузки:

  • ret& at(unsigned int i) и
  • const ret& 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

Вы также можно решить вашу проблему более элегантно, используя лямбды:

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