7

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.

BiagioF
  • 9,368
  • 2
  • 26
  • 50
  • I point my 2 cent in a clang++ bug. – max66 Oct 22 '19 at 12:49
  • It might be related to [CWG 1558](http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558). The code works with clang with the definition of `void_t` [recommended by cppreference](https://en.cppreference.com/w/cpp/types/void_t): [live demo](https://godbolt.org/z/gpsTvO). The reported llvm bug seems to be [here](http://lists.llvm.org/pipermail/llvm-bugs/2017-June/056544.html). – Daniel Langr Oct 22 '19 at 13:29
  • Correction: it is more likely related to [CWG 1980](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1980). See this relevant question: [Multiple SFINAE class template specialisations using void_t](https://stackoverflow.com/q/45948990/580083). – Daniel Langr Oct 22 '19 at 13:49

0 Answers0