wollen die Nichtübereinstimmung zwischen den Schlüsseltypen in einer Karte in Boost.Interprocess Shared Memory effizient überwinden.
Ich erstelle eine Map (in diesem Beispiel von String zu String) im Shared Memory mit Boost.Interprocess. Der Compiler scheint mich zwingen zu wollen, während des Abrufs von der Map Speicher im verwalteten Segment zuzuweisen, nur um (unnötigerweise) den Abfragebegriff zu enthalten.
Ich möchte in der Lage sein, Werte in einer freigegebenen Karte effizienter nachzuschlagen, indem die Schlüssel der Karte mit Instanzen verglichen werden, die sich bereits im nicht freigegebenen Speicher befinden, ohne diese zusätzliche Zuordnung vorzunehmen. Es lehnt jedoch das Kompilieren ab, wenn ich versuche, ein @ zu verwendestd::string
oderconst char *
als Argument für das @ der Karfind
Methode. (Siehe Compiler-Fehlermeldungen unten).
Muss ich eine Art Vergleichsmethode zwischen meinem Shared-Memory-Schlüsseltyp und seinem nicht gemeinsam genutzten Äquivalent definieren std::string
in diesem Beispiel)? Wenn ja, wie soll das aussehen und wie soll ich die Karte verwenden? Wenn nicht, was soll ich tun?
Hier ist der Code, gefolgt von den Compiler-Fehlern. Das Problem ist auf der Unterseite vonmain()
.
// shmap2.cpp
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
//Typedefs of allocators and containers
namespace Shared
{
typedef boost::interprocess::managed_shared_memory
Segment;
typedef boost::interprocess::managed_shared_memory::segment_manager
SegmentManager;
typedef boost::interprocess::allocator< void, SegmentManager >
Allocator;
typedef boost::interprocess::allocator< char, SegmentManager >
CharAllocator;
typedef boost::interprocess::basic_string< char, std::char_traits< char >, CharAllocator >
String;
typedef std::less< String >
StringComparator;
// Definition of the shared map from String to String
// (To avoid confusion, let's strictly use Python-like definitions of "key", "value" and "item")
typedef std::pair< const String, String >
MapItem;
typedef boost::interprocess::allocator< MapItem, SegmentManager >
MapItemAllocator;
typedef boost::interprocess::map< String, String, StringComparator, MapItemAllocator >
Map;
}
int main( void )
{
struct shm_remove
{
shm_remove() { boost::interprocess::shared_memory_object::remove( "MySharedMemory" ); }
~shm_remove(){ boost::interprocess::shared_memory_object::remove( "MySharedMemory" ); }
} remover;
// Create shared memory
Shared::Segment seg( boost::interprocess::create_only, "MySharedMemory", 65536 );
// An allocator instance that can be converted to any allocator< T, Shared::SegmentManager > type
Shared::Allocator alloc( seg.get_segment_manager() );
// An instance of the string comparator, to construct the map
Shared::StringComparator cmp;
// Construct the shared memory map
Shared::Map * myMapPtr = seg.construct< Shared::Map >( "myMap" )( cmp, alloc );
// Here's the problem:
// std::string key( "foo" ); // Compilation fails if you use this.
// char key[] = "foo"; // Compilation fails if you use this.
Shared::String key( "foo", alloc ); // This the only version I can get to work.
// But it forces you to create a copy of
// the key you are searching for, in
// the managed segment.
// This is the point of the exercise:
Shared::Map::iterator it = myMapPtr->find( key );
return 0;
}
Mit einerstd::string
als diekey
:
$ g++ -o shmap2 -D BOOST_ALL_NO_LIB -I ../boost_1_57_0 shmap2.cpp
shmap2.cpp:79:40: error: no matching member function for call to 'find'
Shared::Map::iterator it = myMapPtr->find( key );
~~~~~~~~~~^~~~
../boost_1_57_0/boost/container/detail/tree.hpp:1089:13: note: candidate function not
viable: no known conversion from 'std::string' (aka 'basic_string<char,
char_traits<char>, allocator<char> >') to 'const key_type' (aka 'const
boost::container::basic_string<char, std::__1::char_traits<char>,
boost::interprocess::allocator<char, boost::interprocess::segment_manager<char,
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,
boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >
>') for 1st argument
iterator find(const key_type& k)
^
../boost_1_57_0/boost/container/detail/tree.hpp:1092:19: note: candidate function not
viable: no known conversion from 'std::string' (aka 'basic_string<char,
char_traits<char>, allocator<char> >') to 'const key_type' (aka 'const
boost::container::basic_string<char, std::__1::char_traits<char>,
boost::interprocess::allocator<char, boost::interprocess::segment_manager<char,
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,
boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >
>') for 1st argument
const_iterator find(const key_type& k) const
^
1 error generated.
Mitconst char *
als diekey
:
$ g++ -o shmap2 -D BOOST_ALL_NO_LIB -I ../boost_1_57_0 shmap2.cpp
In file included from shmap2.cpp:17:
In file included from ../boost_1_57_0/boost/interprocess/containers/string.hpp:19:
../boost_1_57_0/boost/container/string.hpp:676:59: error: no matching constructor for
initialization of 'allocator_type' (aka 'boost::interprocess::allocator<char,
boost::interprocess::segment_manager<char,
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,
boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >')
basic_string(const CharT* s, const allocator_type& a = allocator_type())
^
shmap2.cpp:79:46: note: in instantiation of default function argument expression for
'basic_string<char, std::__1::char_traits<char>, boost::interprocess::allocator<char,
boost::interprocess::segment_manager<char,
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,
boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >'
required here
Shared::Map::iterator it = myMapPtr->find( key );
^
../boost_1_57_0/boost/interprocess/allocators/allocator.hpp:140:4: note: candidate
constructor template not viable: requires single argument 'other', but no
arguments were provided
allocator(const allocator<T2, SegmentManager> &other)
^
../boost_1_57_0/boost/interprocess/allocators/allocator.hpp:129:4: note: candidate
constructor not viable: requires single argument 'segment_mngr', but no arguments
were provided
allocator(segment_manager *segment_mngr)
^
../boost_1_57_0/boost/interprocess/allocators/allocator.hpp:134:4: note: candidate
constructor not viable: requires single argument 'other', but no arguments were
provided
allocator(const allocator &other)
^
1 error generated.
AKTUALISIEREN Auf Anregung von sehe habe ich unten versucht, @ zu ersetze
typedef std::less< String >
StringComparator;
mi
typedef struct
{
template< typename T, typename U >
bool operator()( const T & t, const U & u )
const { return t < u; }
} StringComparator;
aber bekam die gleichen zwei Compilerfehler.