Software Craftsman
Software Craftsman

Reputation: 3269

Proper syntax to use std::map access operator [] via std::unique_ptr

My question is really simple. I googled a lot, but somehow I cannot figure it out. I use a C++ std::map with a std::unique_pointer like this:

std::unique_ptr<std::map<int,std::string>> my_map( new std::map<int,std::string>());

Now, I want to use the access operator [] of the map. But I always get a compiler error.

my_map[1] = "XYZ";    // error C2676
my_map->[1] = "XYZ";  // error C2059

Without the std::unique_ptr, my code would be like below, and it works. But how do I do the same via std::unique_ptr? Please help me.

std::map<int,std::string> my_map;
my_map[1] = "XYZ";   // OK!

Modern C++ is welcome and even desired.

Upvotes: 3

Views: 393

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275405

I find (*my_map)[1] to be annoying. The problem is order of operations.

We can use a named operator to invert the order of operations as follows:

namespace easy_op {
  enum class supported_ops {
    index,
    invoke,
  };
  template<class Rhs, supported_ops>
  struct op_t {
    Rhs rhs;
  };
  constexpr static struct do_opt {
    template<class Rhs>
    constexpr op_t<Rhs, supported_ops::index>
    operator[](Rhs&& rhs)const{
      return {std::forward<Rhs>(rhs)};
    }
    template<class Rhs>
    constexpr op_t<Rhs, supported_ops::invoke>
    operator()(Rhs&& rhs)const{
      return {std::forward<Rhs>(rhs)};
    }
    constexpr do_opt() {}
  } const op;
  template<class Lhs, class Rhs>
  constexpr auto operator*( Lhs&& lhs, op_t<Rhs, supported_ops::index>&& rhs )
  -> decltype( (*std::declval<Lhs>())[std::declval<Rhs>()] )
  {
    return (*std::forward<Lhs>(lhs))[std::forward<Rhs>(rhs.rhs)];
  }
  template<class Lhs, class Rhs>
  constexpr auto operator*( Lhs&& lhs, op_t<Rhs, supported_ops::invoke>&& rhs )
  -> decltype( (*std::declval<Lhs>())(std::declval<Rhs>()) )
  {
    return (*std::forward<Lhs>(lhs))(std::forward<Rhs>(rhs.rhs));
  }
}
using easy_op::op;

live example.

std::unique_ptr< std::vector<int> > p = std::make_unique<std::vector<int>>();
*p = {0,1,2,3,4,5};
for(std::size_t i = 0; i < p->size(); ++i) {
    std::cout << p*op[i];
}
std::cout << '\n';

Upvotes: 0

ForEveR
ForEveR

Reputation: 55887

Call operator function manually

my_map->operator[](1)

or dereference pointer and call operator []

(*my_map)[1]

Upvotes: 13

Related Questions