c++dictionarystructptr-vector

error: invalid use of 'Config::testMap'


Here is the code:

#include <iostream>
#include <string>
#include <map>
#include <stdexcept>
#include <boost/ptr_container/ptr_vector.hpp>

struct TestStruct
{
    std::string str1;
    int var1;
};

struct Config
{
    // Map
    typedef std::map< std::string, boost::ptr_vector<struct TestStruct> > testMap;
};

void foo(Config& config)
{
    if (config.testMap.empty())
    {
        std::cout << "It worked!" << std::endl;
    }
    else
    {
        std::cout << "It didn't work!" << std::endl;
    }
    return;
}

int testMain(void)
{
    Config config;

    foo(config);

    return;
}

int main(void)
{
    try
    {
        return testMain(/*argc, argv*/);
    }
    catch(std::exception& err)
    {
        std::cerr << "Error running program: " << err.what() << std::endl;
        return 1;
    }
    catch(...)
    {
        std::cerr << "Program failed with an unknown exception." << std::endl;
        return 1;
    }
}

I'm new to maps - never used one before. I've found many examples of how to use them online. Unfortunately I can't seem to makes sense of more advanced examples of them.

What I'd like to do is create a map with a key (std::string) and a value (boost::ptr_vector<struct>).

I was going to start by just declaring and passing it around successfully. Then I wanted try and figure out how to fill it up.

I ran into an error that is just vague enough I don't know how to interpret it.

Any suggestions on what I've done wrong in the "use" of testMap?

Also, can someone provide some simple example of how I can populate the map up.

Say I want a key of a and a value of str1 = "hello", var1 = 10. How would I do this?

FOLLOW UP QUESTION: In regards to the answer left below by Kerrek SB.

If I do the following...

std::string key   = "a";
TestStruct value = {"hello", 10};
config.testMap[key] = value;

I get the following error:

 error: no match for 'operator=' in 'config->Config::testMap.std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> > > >](((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& key)))) = value'
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note: candidates are: boost::ptr_vector<T, CloneAllocator, Allocator>& boost::ptr_vector<T, CloneAllocator, Allocator>::operator=(std::auto_ptr<boost::ptr_vector<T, CloneAllocator, Allocator> >) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note:                 boost::ptr_vector<T, CloneAllocator, Allocator>& boost::ptr_vector<T, CloneAllocator, Allocator>::operator=(boost::ptr_vector<T, CloneAllocator, Allocator>) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]

If instead I do the .insert() method I get the following error:

instantiated from here
/opt/csw/gcc4/lib/gcc/sparc-sun-solaris2.8/4.3.2/../../../../include/c++/4.3.2/bits/stl_pair.h:106: error: no matching function for call to 'boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >::ptr_vector(const TestStruct&)'
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:50: note: candidates are: boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector(typename boost::ptr_sequence_adapter<T, std::vector<void*, Allocator>, CloneAllocator>::size_type, const typename boost::ptr_sequence_adapter<T, std::vector<void*, Allocator>, CloneAllocator>::allocator_type&) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note:                 boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector(std::auto_ptr<boost::ptr_vector<T, CloneAllocator, Allocator> >) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note:                 boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector(const typename boost::ptr_sequence_adapter<T, std::vector<void*, Allocator>, CloneAllocator>::allocator_type&) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note:                 boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector() [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:35: note:                 boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >::ptr_vector(const boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >&)

FOLLOW UP:

From what I've researched this is not possible.

You cannot use a ptr_vector in a map. (so I've been told) Due to ownership/copy issues?

"What happens when you attempt to copy a ptr_vector, which is bound to happen inside a map? The pointer containers model exclusive ownership of pointers.

You can do this with C++0x and std::move, but that won’t help you here."

Can anyone provide a counter example?


Solution

  • From what I've researched this is not possible.

    You cannot use a ptr_vector in a map. (so I've been told) Due to ownership/copy issues?

    "What happens when you attempt to copy a ptr_vector, which is bound to happen inside a map? The pointer containers model exclusive ownership of pointers.

    You can do this with C++0x and std::move, but that won’t help you here."