Here's some code that works in GCC, Clang and MSVS (at least, those versions currently available on Compiler Explorer):
template <typename T, auto T::* MemberPtr>
struct Foo
{
Foo(const T& e) : _e(e) {}
void operator()() const
{
(_e.*MemberPtr)();
}
private:
const T& _e;
};
struct Bar
{
void baz() const {}
auto bind()
{
using BindingType = Foo<Bar, &Bar::baz>;
return BindingType(*this);
}
};
int main()
{
Bar i;
i.bind();
}
Starting from v16.6.1, however, MSVS rejects it:
Severity Code Description Line
Error C2973 'Foo': invalid template argument 'int' 23
Error E2886 cannot deduce 'auto' template parameter type "auto T::*" from "void (Bar::*)()" 21
Error C2440 'specialization': cannot convert from 'overloaded-function' to 'auto Bar::* ' 22
Error C3535 cannot deduce type for 'auto Bar::* ' from 'int' 23
Error C2440 'specialization': cannot convert from 'int' to 'int Bar::* ' 23
The code can be "fixed" in that version by taking out the T::* qualifier for MemberPtr; so:
template <typename T, auto MemberPtr>
What does the standard say about this? Is VS v16.6.1 introducing a new regression, or is it now diagnosing code that was always subtly broken?