3

EDIT: This question is not a dupe. This is why...

I do not want to test: 1) if a given type is a map (pseudocode: type=="map"), but 2) if the type of a given variable is map (pseudocode: typeof(var)=="map").
Having #1 (as in the linked question Checking if a type is a map) is not enough. One has to chain it with a function that gets the type from the var. I did not find that, so far (typeid does not seem to do the job).


Now the original question

I want to check if a given variable var is a map (regardless of the types of first and second), and without declaring any other variable.

Is this possible? How? Note: I don't care about getting the human-readable form "map", but only about getting a boolean for (pseudocode: typeof(var)=="map").

Is demangling (which is non-portable) the only way? Unmangling the result of std::type_info::name


Posting an answer here (inspired by https://stackoverflow.com/a/35293682/2707864, which solves the issue for a type, not a variable).

template<typename T>
constexpr bool is_map(const T&) { return false; }

template<typename Key, typename Value, typename Order, typename Allocator>
constexpr bool is_map(const std::map<Key, Value, Order, Allocator>&) {
   return true;
}
JFMR
  • 23,265
  • 4
  • 52
  • 76
  • 4
    Can you show what code you would use that utilizes this ability? – Galik Feb 07 '20 at 12:35
  • 1
    There's many [type traits](https://en.cppreference.com/w/cpp/types#Type_traits_.28since_C.2B.2B11.29) which could possibly be used. – Some programmer dude Feb 07 '20 at 12:35
  • 1
    And why do you need to do this? What is the actual problem that think such a check would solve? Please ask about that directly instead. – Some programmer dude Feb 07 '20 at 12:36
  • If you want a std::map specific template specialization SFINAE or partial specialization would be the way to do it. – Sebastian Hoffmann Feb 07 '20 at 12:37
  • @Galik - This would be embedded in a large code... I see no way of posting anything helpful as such. I could post a MCVE, but it wouldn't add anything. If you still think it may be useful, I could put this MCVE together. – sancho.s ReinstateMonicaCellio Feb 07 '20 at 12:54
  • @Someprogrammerdude - There was another problem that led me to this question. I was then interested in this specific question. Asking about the other problem would be a different question, which I would post later on. There is often a chain of problems that leads to solutions and learning on the road. I don't think one *should* always post the *original problem/question* instead of the *derived problem/question*. That should be up to the OP. Of course, I would welcome comments on both, and that is why I would post both. Thanks! – sancho.s ReinstateMonicaCellio Feb 07 '20 at 12:57
  • @sancho.sReinstateMonica Note that an `std::map` class template takes more template parameters than just two. For example, an `std::map` with an allocator other than the default will result in `false` when calling your `is_map()`. By making them `constexpr` we can use it when a compile-time constant is needed. – JFMR Feb 08 '20 at 09:56
  • 1
    @眠りネロク - Great... I put it together in a rush, and I knew I was leaving some cases out. Now we have to wait for the question to be reopened. – sancho.s ReinstateMonicaCellio Feb 08 '20 at 10:43

1 Answers1

4

You can use a type trait like this:

template< typename T >
struct is_map : std::false_type {};

template< typename Key, typename Value, typename Order, typename Allocator >
struct is_map< std::map< Key, Value, Order, Allocator > > : std::true_type {};

struct Foo
{
    std::map< int, float > m_map;
    int m_int;
};

static_assert(is_map< decltype(Foo().m_map) >::value);
static_assert(!is_map< decltype(Foo().m_int) >::value);
Andrey Semashev
  • 10,046
  • 1
  • 17
  • 27
  • 1
    The functions have a caveat that they may initiate type conversion from a different type and give a wrong answer. – Andrey Semashev Feb 07 '20 at 12:59
  • 1
    Sorry again, those were not ordinary functions, but function *templates*. As far as I know, *implicit user-defined conversions* are **never** considered *during template argument deduction*. What am I missing? Thank you. – JFMR Feb 07 '20 at 13:24
  • 1
    You're right, the `is_map(const T&)` overload would get picked. Still, I prefer to keep the type trait version as it doesn't involve template parameter deduction and overload resolution and directly operates on types. – Andrey Semashev Feb 07 '20 at 13:38
  • Alright, thanks for clarifying, it has been a very constructive thinking exercise. – JFMR Feb 07 '20 at 13:40
  • Usage example is given in the answer. `is_map< decltype(var) >::value`. – Andrey Semashev Feb 07 '20 at 15:03
  • 1
    Perhaps your method can be adapted to a simpler usage (as in `is_map(var)`). I have posted one such option at the end of the question. – sancho.s ReinstateMonicaCellio Feb 07 '20 at 16:05