I have problem with function templates using vs14 compiler. So the following code demonstrates the issue.
#include <iostream>
using namespace std;
class Class {
public:
int memberFoo() {
return 0;
}
};
template <class VariableT, class C>
void nothing(const VariableT C::*memberV) {
cout << "Pointer to member variable";
}
template <class R, class C>
void nothing(R (C::*memberF)()) {
cout << "Pointer to member function";
}
int main() {
nothing(&Class::memberFoo);
return 0;
}
Compiler lets me know that nothing
function is ambiguous. When I see the output, it seems to have other behaviour than I expected.
In the first nothing
function, compiler deduces VariableT
as int(void)
. Actually it's not that weird, but I supposed that the second one will be more suitable and will be matched. What is more interesting if you remove const
in first overloaded function, the program will compile correctly.
Can you suggest me how to deal with this, please?
You can fix it by using some handy type_traits, is_member_function_pointer and is_member_object_pointer:
template <class R, class C>
void nothing(R (C::*memberF)())
{
std::cout << "Pointer to function" << std::endl;
}
template <class VariableT, class C>
auto nothing(const VariableT C::* memberV)-> typename std::enable_if<std::is_member_object_pointer<decltype(memberV)>::value>::type
{
cout << "Pointer to member variable";
}
Live Demo
The default type from std::enable_if
is void
, so the return type remains void
.
From your post it sounds like the member function template should be instantiated, but Visual Studio and Clang both yell about ambiguity, which I suppose is fair, given Type Class::*
, you could infer a pointer to member or pointer to member function, assuming that a substitution of ReturnType()
is valid for Type
(which is what we're seeing).
So I decided to skip all that and take advantage of the trailing return type to interrogate the parameter directly.
Including text from link in T.C.'s comment
Section: 14.8.2.1 [temp.deduct.call]
It is not clear whether the following is well-formed or not:void foo(){} template<class T> void deduce(const T*) { } int main() { deduce(foo); }
Implementations vary in their treatment of this example.
Indeed, you noticed that removing const
also removed the ambiguity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With