edit:
OK I figured it out. I was using false_type
and true_type
as an argument to enable_if
when I should have just used bool
. :x
Further, I have decided that a is_map_like
class would be better to check if value_type
is like, std::pair<const Tkey, Tmapped>
. So, my new traits class looks like this:
template<class Tcontainer>
struct is_map_like
{
private:
template<class TvalueType>
struct test
{
static const bool bvalue = false;
};
template<class TkeyType, class TmappedType>
struct test<std::pair<const TkeyType, TmappedType>>
{
static const bool bvalue = true;
};
public:
static const bool bvalue = test<typename Tcontainer::value_type>::bvalue;
};
I want to create a is_map_like
type traits class that checks for key_type
and mapped_type
. I am having a hard time building this. For now I'd like to just check for key_type
. I have the following so far:
template<class T>
struct is_map_like
{
private:
template<typename C> static std::true_type test(typename C::key_type*);
template<typename C> static std::false_type test(...);
public:
typedef decltype(test<T>(0)) value;
};
value
here seems to always return false_type
. As I understand, SFINAE should allow me to choose the right test
overload based on whether C::key_type
is accessible.
Here is how I'm testing: First, a struct that is specialized using enable_if
on is_map_like
:
// a class that will be specialized only for map-like types
template<class T, class Enable = void>
struct MyStruct
{
static void fn() { DebugLog(L"T is not a map type"); }
};
template<class T>
struct MyStruct<T, typename std::enable_if<is_map_like<T>::value>::type>
{
static void fn() { DebugLog(L"T is INDEED a map type"); }
};
And here's how I call it at runtime:
void test_is_map()
{
MyStruct<std::vector<int>>::fn();
MyStruct<std::map<int, int>>::fn();
}
The output:
T is not a map type T is not a map type
What am I doing wrong? Why is the test(typename C::key_type*)
not used even for the map
, which indeed has a key_type
? Or is the problem with my usage of decltype
?
And bonus: are there any debugging techniques for this? How can I inspect how specializations are chosen, or even get a verification at compile-time about expansion? Maybe there are VS-specific extensions or compile-time debugging tools?
The value in the SFINAE structure is a type.
Make it:
static constexpr bool value = decltype(test<T>(0))::value;
and it will work