Reputation:
I had to use pointers to member functions in various circumstances before. Typically, I used mem_fun
. However, this is the first time I am trying to use it on a member template that returns auto
. It does work for auto
return 'type' if the member is not a template and it does work for a member template if the return type is specified. Also, I tried passing the expected types directly into mem_fun()
and it did not help.
Any alternative solutions that do not rely on mem_fun()
will also be appreciated.
Below is the code that does not compile due to the following error:
no matching function for call to 'mem_fun()'.
It should be noted that if auto
is replaced by int
the code compiles. Also, if auto is left, but template<int N>
and <1>
, the code also compiles and works as expected.
class Q
{
public:
int myq;
template<int N>
auto mymethod(int a)
{
std::cout << myq*a << std::endl;
}
void setint(int a)
{
myq = a;
}
};
int main()
{
boost::function<void (int)> p_member;
Q q;
p_member = std::bind1st(
std::mem_fun(
&Q::mymethod<1>
),
&q
);
q.setint(1);
p_member(100);
//...
}
Upvotes: 0
Views: 219
Reputation:
This is not really specific to auto
, it's a general limitation of GCC. There are situations where it just does not realise that if after specifying template arguments there is only one possible function it could refer to, it refers to that function. For most code, it doesn't matter, and for most situations where it does matter, GCC has worked around those limitations, but sometimes it does come to the surface. Quite a while ago I reported a similar issue:
template <int> void f() {}
int main() { return f<0> != f<0>; }
This should compare the address of f<0>
with the address of f<0>
, so should return zero, but GCC cannot figure out that f<0>
is not overloaded, and complains with:
error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘<unresolved overloaded function type>’ to binary ‘operator!=’
Here, a workaround is adding a pointless no-op that convinces the compiler to try a bit harder in figuring out the type: return &f<0> != &f<0>;
does work.
A similar approach can also be used for your code. Although the &
operator cannot be added here, other no-ops do work:
p_member = std::bind1st(
std::mem_fun(
true ? &Q::mymethod<1> : nullptr
),
&q
);
I see no reason for thinking your code might be invalid. It's accepted as it is by other compilers (at least clang), and if it were invalid, then surely my workaround here would be invalid for the exact same reason.
Upvotes: 2