SFINAE `std::void_t` class template specialisation

91 Views Asked by At

Using SFINAE, I need to detect some properties of a container.

For example:

#include <type_traits>
#include <vector>

template <typename Container, typename = void>
struct Trait {};

template <typename Container>
struct Trait<
    Container,
    std::enable_if_t<std::is_integral_v<typename Container::value_type>>> {
  static constexpr bool foo = false;
};

template <typename Container>
struct Trait<
     Container, 
     std::enable_if_t<std::is_floating_point_v<typename Container::value_type>>> {
  static constexpr bool foo = true;
};

static_assert(Trait<std::vector<int>>::foo == false);
static_assert(Trait<std::vector<double>>::foo == true);

The above code compiles and works as expected (both on clang and gcc). Check here.

However, if I slightly modify the code wrapping the template type inside a std::void_t:

template <typename Container>
struct Trait<
    Container,
    std::void_t<std::enable_if_t<std::is_integral_v<typename Container::value_type>>>> {
  static constexpr bool foo = false;
};

template <typename Container>
struct Trait<
    Container, 
    std::void_t<std::enable_if_t<std::is_floating_point_v<typename Container::value_type>>>> {
  static constexpr bool foo = true;
};

then, it works and compiles on gcc but it is rejected on clang. Check here.

In particular, clang complains about the redifinition of Trait.


Questions (about the second version of code):

1) Is this a clang bug?

2) In case clang is standard complaint (i.e., it is a gcc bug), why adding std::void_t creates a redefinition of Trait? I expect that SFINAE would prevent the redifinition.

0

There are 0 best solutions below