mardi 2 mai 2017

Is this considered valid c++11 or c++14? Or is gcc/clang getting it wrong?

While trying to solve Is it possible to tell if a class has hidden a base function in C++?, I generated this:

#include <type_traits>
#include <iostream>

#define ENABLE_IF(...) std::enable_if_t<(__VA_ARGS__), int> = 0

template<class T, class B, ENABLE_IF(std::is_same<void(T::*)(), decltype(&T::x)>::value)>
auto has_x_f(T*) -> std::true_type;

template<class T, class B>
auto has_x_f(B*) -> std::false_type;

template<class T, class B>
using has_x = decltype(has_x_f<T, B>((T*)nullptr));

template<typename T>
struct A
{
  void x() {}

  static std::true_type  test(void(T::*)());
  static std::false_type test(void(A<T>::*)());
  static const bool x_hidden;

  template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
  void y(R value)
  {
     std::cout << "x() is hidden" << std::endl;
  }

  template <typename R, ENABLE_IF(std::is_same<T, R>::value && !x_hidden)>
  void y(R value)
  {
     std::cout << "x() is not hidden" << std::endl;
  }

  //using t = std::integral_constant<bool, x_hidden>;
};

struct B : A<B>
{
    void x() {}
};

struct C : A<C>
{
};

template<typename T>
const bool A<T>::x_hidden = has_x<T, A<T>>::value;

int main()
{
  B b;
  C c;

  std::cout << "B: ";
  std::cout << b.x_hidden << std::endl;
  std::cout << "C: ";
  std::cout << c.x_hidden << std::endl;

  std::cout << "B: ";
  b.y(b);
  std::cout << "C: ";
  c.y(c);

  return 0;
}

Which outputs what I want:

B: 1
C: 0
B: x() is hidden
C: x() is not hidden

clang and gcc both compile and execute this "correctly", but vc++ doesn't (though I am aware that there are problems with it working properly with expressions similar to template <typename T> ... decltype(fn(std::declval<T>().mfn()))).

So my question is, is this considered valid or will it break later on? I'm also curious about the x_hidden being able to be used as a template parameter in the functions but not being able to use it in using t = std::integral_constant<bool, x_hidden>. Is that just because the template's type isn't fully declared at this point? If so, why did using it work for the function declarations?

Aucun commentaire:

Enregistrer un commentaire