deseja superar com eficiência a incompatibilidade entre os tipos de chave em um mapa no Boost.
Estou criando um mapa (de string para string neste exemplo) na memória compartilhada usando Boost.Interprocess. O compilador parece querer me forçar, durante a recuperação do mapa, a alocar memória no segmento gerenciado apenas para (desnecessariamente) conter o termo de consulta.
Eu gostaria de poder pesquisar valores em um mapa compartilhado com mais eficiência, combinando as chaves do mapa com instâncias que já estão na memória não compartilhada, sem executar essa alocação extra. Mas ele se recusa a compilar se eu tentar usar umstd::string
ouconst char *
como o argumento para o mapafind
método. (consulte as mensagens de erro do compilador na parte inferior).
Preciso definir algum tipo de método comparador entre meu tipo de chave de memória compartilhada e seu equivalente não compartilhado (std::string
neste exemplo)? Nesse caso, como isso deve ser e como devo fazer o mapa usá-lo? Caso contrário, o que devo fazer?
Aqui está o código, seguido pelos erros do compilador. O problema está no fundo domain()
.
// 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;
}
Com umstd::string
Enquanto okey
:
$ 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.
Comconst char *
Enquanto okey
:
$ 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.
ATUALIZAR: seguindo a sugestão de, abaixo, tentei substituir
typedef std::less< String >
StringComparator;
com
typedef struct
{
template< typename T, typename U >
bool operator()( const T & t, const U & u )
const { return t < u; }
} StringComparator;
mas obteve os mesmos dois erros do compilador.