Reputation: 81
I try to write a template meta function to test "is a type T
has a member type, named type
".
here is the code:
#include <iostream>
#include <type_traits>
template <typename T, typename E = void>
struct has_type;
// branch 1
template <typename T, typename E>
struct has_type : std::false_type {};
// branch 2
template <typename T>
struct has_type<
T, std::enable_if_t<std::is_same_v<typename T::type, typename T::type>, T>
> : std::true_type {};
struct with_type {using type = void;};
struct without_type {};
int main()
{
std::cout<< has_type< with_type >::value <<std::endl;
std::cout<< has_type< without_type >::value <<std::endl;
return 0;
}
I imagined, compiler will first try to use branch 2, if the type T
has the member type type
, we get std::true_type
.
Or fail to find T::type
, then SFINAE and use branch 1, we get std::false_type
But the two output is both false
.
Is there anything I understand wrong?
Upvotes: 1
Views: 73
Reputation: 172964
The branch 1, i.e. the primary template, the default value of the 2nd template parameter is void
; to make the branch 2, i.e. the specialization to be selected, the 2nd template argument should yield type void
instead of T
, when the condition is satisfied.
// branch 2
template <typename T>
struct has_type<
T, std::enable_if_t<std::is_same_v<typename T::type, typename T::type>, void>
// ^^^^
> : std::true_type {};
Or just
template <typename T>
struct has_type<
T, std::void_t<typename T::type>
> : std::true_type {};
Upvotes: 4