This is a follow-up question to MSVC fails to deduce template argument
I am unable to find any combination that works on Visual Studio Enterprise 2019 (VS 16.11, MSVC 19.29). clang, g++ and MSVC 19.33 and later (without /permissive-) compile this code. MSVC 19.29 does not even if using /permissive-.
It looks a lot like a SFINAE bug.
#include <type_traits>
struct Prop1 {
constexpr Prop1() {};
};
struct Prop2 {
constexpr Prop2() {};
};
constexpr const Prop1 i;
constexpr const Prop2 j;
// the goal is that def() should have separate implementations
// for member variables and member functions
// (in my real code Prop1/Prop2 have default values, thus the enable_if
// is required, in the minimal repro this is not the case)
struct Klass {
template <auto Klass::*MEMBER, const Prop2 &P,
typename = std::enable_if_t<std::is_member_object_pointer_v<decltype(MEMBER)>>>
void def() {}
template <auto Klass::*MEMBER, const Prop1 &P,
typename = std::enable_if_t<std::is_member_function_pointer_v<decltype(MEMBER)>>>
void def() {}
void fn();
int var;
};
void Klass::fn() {}
int main() {
Klass k;
k.def<&Klass::fn, i>();
k.def<&Klass::var, j>();
}
>Solution :
I am unable to find any combination that works on Visual Studio Enterprise 2019 (VS 16.11, MSVC 19.29)
Here is a workaround that uses SFINAE in the return type of the function template. This seems to be a msvc bug.
struct Klass {
template <auto Klass::*MEMBER, const Prop2 &P>
//using SFINAE in the return type
typename std::enable_if_t<std::is_member_object_pointer_v<decltype(MEMBER)>> def() {}
template <auto Klass::*MEMBER, const Prop1 &P>
//using SFINAE in the return type
typename std::enable_if_t<std::is_member_function_pointer_v<decltype(MEMBER)>> def() {}
void fn();
int var;
};