Const map and its size

Viewed 775

I have a std::map which cannot change at runtime. Thus, I have marked it const I cannot mark it constexpr, since has a non-literal type.

Can I deduce the size of this map at compile time?

#include <map>
#include<string>

int main (){
    const std::map <int, std::string> my_map { 
      { 42, "foo" }, 
      { 3, "bar" } 
    };

    constexpr auto items = my_map.size();
    return items;
}

This does not compile with the error:

:10:20: error: constexpr variable 'items' must be initialized by a constant expression

constexpr auto items = my_map.size();

               ^       ~~~~~~~~~~~~~

:10:35: note: non-constexpr function 'size' cannot be used in a constant expression

constexpr auto items = my_map.size();
3 Answers

Unfortunately, you can't use std::map and std::string in constexpt context. If it's possible, consider switching to array and string_view:

int main() {
  constexpr std::array my_map{
      std::pair<int, std::string_view>{ 42, "foo" },
      std::pair<int, std::string_view>{ 3, "bar" }
  };
  constexpr auto items = my_map.size();
  return items;
}

And then using constexpr std algorithms

Can I deduce the size of this map at compile time?

No. Since my_map is not a compile time constant, you cannot use it at compile time.

The standard does not provide a compile time map but there should be libraries out there or you can make your own if you really need it.

It is possible if you initialize the map via a template function

template<class... Args>
std::pair<std::integral_constant<std::size_t, sizeof...(Args)>, std::map<int, std::string>>
make_map(Args&& ...args)
{
    return {{}, std::map<int, std::string>({std::forward<Args>(args)...})};
}

int main() {
    const auto& p = make_map(
         std::make_pair( 42, std::string("foo") ), 
         std::make_pair( 3, std::string("bar") ) 
    );

    constexpr std::size_t size = std::decay_t<decltype(p.first)>::value;
    const auto& my_map = p.second;
    //or const auto my_map = std::move(p.second);
}
Related