Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#6711 closed Feature Requests (wontfix)

with unordered_map using interprocess basic_string in shared memory, find and [] are annoying

Reported by: jdy@… Owned by:
Milestone: To Be Determined Component: None
Version: Boost 1.49.0 Severity: Problem
Keywords: interprocess, unordered_map, container Cc: jdy@…, igaztanaga@…

Description

When using an interprocess basic string such as:

typedef boost::interprocess::allocator<
        char,
        boost::interprocess::managed_mapped_file::segment_manager
  >                                         char_allocator_t;

typedef boost::interprocess::basic_string<
        char, 
        std::char_traits<char>,
        char_allocator_t
  >                                      key_type;

map, flat_map (and unordered_map) all require that one have an externally created temporary of that type (key_type) created that can temporarily hold the results of a std::string or char*. This requires code of the form:

      // A temporary string that allocates from the mapped file
      struct shm_clean { // cleanup shared memory on stack-unwind
        shm_clean() { 
          boost::interprocess::shared_memory_object::remove("StupidSharedMemory");
        }
        ~shm_clean() {
          boost::interprocess::shared_memory_object::remove("StupidSharedMemory");
        }
      } cleaner;
      boost::interprocess::managed_shared_memory
stupid(boost::interprocess::create_only ,"StupidSharedMemory" ,500);
      key_type key_val(stupid.get_segment_manager());

mymap_in_shared_memory[key_val = mystring.c_str()] = junk;

This is barely ok when we are working with mutable memory regions, but when I am working in a read-only memory map, it is annoying.

Please see this thread:

http://thread.gmane.org/gmane.comp.lib.boost.devel/228874

Bug posted at request of Ion Gaztañaga

See sister ticked for boost::containers

https://svn.boost.org/trac/boost/ticket/6710

Joel

Change History (11)

comment:1 by Daniel James, 11 years ago

Resolution: wontfix
Status: newclosed

Closing as "won't fix", since boot unordered is an implementation of the standard unordered containers, and this would be a break from the standard. It would also be worse when using std::equal_to or boost::hash since it would have to cast for every call to those function objects rather than just once for the call to operator[].

comment:2 by olafvdspek@…, 11 years ago

The standard doesn't require you to not have extra find() overloads, does it?

comment:3 by Daniel James, 11 years ago

It does, because it can break valid code. Consider this:

#include <cassert>
#include <functional>

struct source {};

struct value {
    value(source&&) {}
};

void foo(value const& x) { std::equal_to<value>(x); }

#if defined(ADD_TEMPLATE)
template <typename T>
void foo(T const& x) { std::equal_to<value>(x); }
#endif

int main() {
    foo(source());
}

Note that ADD_TEMPLATE adds a template overload, as you're suggesting. Defining ADD_TEMPLATE causes it to fail:

$ g++-mp-4.7 --std=c++0x demo.cpp 
$ g++-mp-4.7 --std=c++0x demo.cpp -DADD_TEMPLATE
demo.cpp: In instantiation of 'void foo(const T&) [with T = source]':
demo.cpp:19:17:   required from here
demo.cpp:15:24: error: invalid initialization of reference of type 'const value&' from expression of type 'const source'
demo.cpp:9:6: error: in passing argument 1 of 'void f(const value&)'

The same could happen if a template overload was added for find.

comment:4 by Olaf van der Spek <olafvdspek@…>, 11 years ago

VC11 says "error C2082: redefinition of formal parameter 'x'" for the first "std::equal_to<value>(x);"

Without equal_to(), it compiles fine.

Even if it didn't, why not just replace the original find() with a template variant?

comment:5 by anonymous, 11 years ago

Sorry, I messed up that example, here's a better one. This one doesn't use rvalue references because I don't have access to an appropriate compiler at the moment, but it demonstrates why a template method would break valid code (foo calls std::equal_to in the same way that find does):

#include <functional>

struct source {};

struct value {
    value(source&) {}
    bool operator==(value const&) const { return true; }
};

struct pseudo_container
{
    std::equal_to<value> eq;

#if defined(USE_A_TEMPLATE)
    template <typename T>
    void foo(T const& x) {
        eq(x, x);
    }
#else
    void foo(value const& x) {
        eq(x, x);
    }
#endif
};

int main() {
    pseudo_container x;
    source s;
    x.foo(s);
}

comment:6 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Isn't that because the value constructor takes a non-const & to source? With const& it works.

comment:7 by anonymous, 11 years ago

But value types are allowed to use non-const constructors from arbitrary types, I can't stop them doing that.

comment:8 by anonymous, 11 years ago

Sorry, 'are allowed to construct with non-const references from arbitrary types'.

comment:9 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Hmm, equal_to is the real problem, as it requires the two types to be the same. You'd need an equal_to variant that doesn't.

comment:10 by Daniel James, 11 years ago

Yes, but equal_to is actually a template parameter, whose concept is defined by the standard so I can't change it.

comment:11 by Olaf van der Spek <olafvdspek@…>, 11 years ago

That sucks :p

Note: See TracTickets for help on using tickets.