0

I have the following problem in a c++-project at my university:
I want to store some objects of Class1 by using a map. Because of the design of my project the class that holds the map as a member variable does not create the objects to store in the map. My research on this forum tells me to use unique_ptr to pass those objects.

When combining those two ideas in a test projects for experiments:

#include <iostream>
#include <memory>
#include <unordered_map>

typedef std::unique_ptr<std::string> string_ptr;

class Class1 {
public:
    std::unordered_map<std::string, string_ptr> my_unordered_map;

    Class1() : my_unordered_map(){
    }

    void addTo(string_ptr ptr) {
        std::string string = *ptr;
        std::cout << string << std::endl;
        my_unordered_map[0] = std::move(ptr);
    }
};


int main() {
    std::cout << "Process started!"<< std::endl;

    string_ptr ptr;
    ptr = std::make_unique<std::string>("text");

    Class1 cont;
    cont.addTo(std::move(ptr));


}

it compiles, but throws a

terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid

at runntime.

I also tried changing void addTo(string_ptr ptr) to addTo(string_ptr &ptr) as suggested in other posts, but the problem remained the same.

Now, whats the problem? Is it:
a) A design mistake to not let Class1 create the objects by itself. C++ inserting unique_ptr in map would answer my question in this case.
-- or --
b) Something else my small knowledge of c++ lets me miss?

Sidenote: ofc the objects i want to store in those pointers are not strings.

CharJ
  • 67
  • 5

2 Answers2

2

Your problem has nothing to do with unique_ptr. It has nothing to do with your value object at all. It is actually with your key. Unfortunately, the integer literal 0 (and only 0, and not an int variable with the value 0) can be treated as a pointer of any type. And also unfortunately, std::string has an implicit conversion constructor from char const*. So when you do this:

my_unordered_map[0] = std::move(ptr);

Since your key type is std::string, you are implicitly constructing a std::string from an null pointer. That is your error.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
1

Here

my_unordered_map[0] = std::move(ptr);

you are passing int as key, but my_unordered_map expects std::string as key, solution:

my_unordered_map[string] = std::move(ptr);

terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_M_construct null not valid

std::string has implicit conversion constructor from char const*, it means attempt to construct std::string from NULL pointer, what causes this error.

If you would need empty string, do following

my_unordered_map[std::string("")] = std::move(ptr);
kocica
  • 6,412
  • 2
  • 14
  • 35
  • I doubt using an empty string as key is what the OP actually wants. – user0042 Aug 22 '17 at 18:48
  • Oh my god. Not even coding for 10hrs straight is an excuse for this fail. As i never worked with uniqu_ptrs before i was expecting some complicated reason for this cryptic error massage. In fact it was just me using 0 instead of a valid string... Thank you for your time! – CharJ Aug 22 '17 at 18:49
  • It happens :-) everything ok now ? – kocica Aug 22 '17 at 18:52