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.