I am trying to bind a member function at or operator[] of std::array, but the compiler (gcc 7.3) says that it can't determine the typename _Func. So I had created my own struct array to see where the problem is. But it works fin in this case.
#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;
}
The compile error is:
no matching function for call to '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;
}
I still don't know how to specify which version of function I want to call, how to bind the const version and the non-const one?
Since you have two overloads:
ret& at(unsigned int i)
andconst ret& at(unsigned int i) const
compiler doesn't know which function overload you really want to bind to. Therefore, you need to cast function pointer to the exact function signature.
This would work:
auto x = std::bind(static_cast<int&(my_arr<int, 3>::*)(unsigned int)>(&my_arr<int,3>::at), _1, 0);
Check it out live
You can also solve your problem in a more elegant way by using lambdas:
auto x2 = [&ma](auto const p) { return ma.at(p); };
std::cout << x2(0) << std::endl; // output: 1