Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

MSVC fails to specialize template with `std::enable_if` and a non-type argument

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#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>();
}

Demo

>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;
};

Working demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading