Ich möchte erreichen, was in der Antwort auf this Frage erreicht wurde, aber für einen Vektor von Strings, d. Ich möchte in der Lage sein, gemeinsamen Code zu schreiben, der entweder mit Heap-Speicher oder Shared Memory verwendet werden kann. Ich habe den Code emuliert und eine Klasse geschrieben, um einen Vektor von Strings zu implementieren, der sowohl mit Heap-Speicher als auch mit gemeinsam genutztem Speicher funktionieren würde. Ich habe es größtenteils funktioniert. Wenn ich jedoch versuche, einen Shared-Memory-Vektor von Strings aus einem Heap-zugewiesenen Vektor von Strings zu initialisieren/erstellen, erhalte ich Kompilierungsfehler. In der Frage, auf die oben verwiesen wird, wurde Shared-Memory-Vektor aus einem nicht geteilten Speichervektor initialisiert (um zu zitieren "das funktioniert wegen ... MAGIC!"). Nicht sicher, ob es, weil diese Frage mit einem Vektor von Ints handelte, die leicht kopierbar und beweglich sind. Ich habe den Kopierkonstruktor für die Shared-Memory-String-Klasse zur Verfügung gestellt, aber es funktioniert immer noch nicht. Ich habe meinen Code unten zur Verfügung gestellt (den Code auskommentiert, der mir Kompilierungsfehler gibt). Jede Hilfe wird geschätzt. Vielen Dank.C++ Boost Interprozess Austausch (Kopie) nicht freigegebenen und geteilten Zeichenfolge Vektor
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <iostream>
#include <string>
#include <sstream>
namespace bip = boost::interprocess;
namespace generic
{
template <typename T, typename Alloc/* = std::allocator<T>*/ >
using vector = bip::vector<T, typename Alloc::template rebind<T>::other >;
template <typename Alloc/* = std::allocator<T>*/ >
using GenericString = bip::basic_string<char, std::char_traits<char>
, typename Alloc::template rebind<char>::other>;
template <typename Alloc>
class String
{
public:
typedef Alloc allocator_type; // ties in with uses_allocator/scoped_allocator
String(Alloc alloc = Alloc())
: mString(alloc)
{
}
String(const std::string str, Alloc alloc = Alloc())
: mString(str.c_str(), alloc)
{
}
String(const char* str, Alloc alloc = Alloc())
: mString(str, alloc)
{
}
template <typename OtherAlloc>
String(String<OtherAlloc> const& other, Alloc alloc = Alloc())
: mString(other.mString.begin(), other.mString.end(), alloc)
{
}
std::string ToString() { return std::string(mString.begin(), mString.end()); }
friend std::ostream& operator<<(std::ostream& os, const String& str)
{
os << str.mString;
return os;
}
private:
template<typename OtherAlloc> friend struct String;
GenericString<Alloc> mString;
};
template <typename Alloc>
class StringVector
{
public:
typedef Alloc allocator_type; // ties in with uses_allocator/scoped_allocator
typedef vector<String<Alloc>, Alloc> GenericStringVector;
using Iterator = typename GenericStringVector::iterator;
using ConstIterator = typename GenericStringVector::const_iterator;
StringVector(Alloc alloc = Alloc())
: mStrings(alloc)
{
}
template <typename OtherAlloc>
StringVector(StringVector<OtherAlloc> const& other, Alloc alloc = Alloc())
: mStrings(other.mStrings.begin(), other.mStrings.end(), alloc)
{
}
void Add(const String<Alloc> str) { mStrings.emplace_back(str); }
void Remove(Iterator iter) { mStrings.erase(iter); }
void Clear() { mStrings.clear(); }
void Print() const
{
std::cout << "[";
for (ConstIterator it = mStrings.begin(); it != mStrings.end(); it++)
std::cout << (it == mStrings.begin() ? "" : ", ") << *it;
std::cout << "]\n";
}
private:
template<typename OtherAlloc> friend struct StringVector;
GenericStringVector mStrings;
};
}
namespace heap
{
using VAlloc = std::allocator<void>;
using String = generic::String<VAlloc>;
using StringVector = generic::StringVector<VAlloc>;
}
namespace shared
{
using VAlloc =boost::container::scoped_allocator_adaptor<
bip::allocator<void, bip::managed_shared_memory::segment_manager> >;
using String = generic::String<VAlloc>;
using StringVector = generic::StringVector<VAlloc>;
}
int main(void)
{
struct shm_remove {
shm_remove() { bip::shared_memory_object::remove("MySharedMemory"); }
~shm_remove() { bip::shared_memory_object::remove("MySharedMemory"); }
} remover;
std::cout << "Heap based storage: \n";
heap::StringVector svec;
svec.Add(heap::String("test1"));
svec.Add(heap::String("test2"));
svec.Add(heap::String("test3"));
svec.Add(heap::String("test4"));
svec.Print();
std::cout << "Shared memory storage: \n";
bip::managed_shared_memory seg(bip::create_only, "MySharedMemory", 65536);
shared::VAlloc shalloc(seg.get_segment_manager());
shared::StringVector sh_svec(shalloc);
sh_svec.Add(shared::String("test1", shalloc));
sh_svec.Add(shared::String("test2", shalloc));
sh_svec.Add(shared::String("test3", shalloc));
sh_svec.Add(shared::String("test4", shalloc));
sh_svec.Print();
shared::StringVector sh_svec2(sh_svec, shalloc);
sh_svec2.Print();
//shared::StringVector sh_svec3(svec, shalloc); // gives compile error :(
//sh_svec3.Print();
}
Einschließlich Kompilierungsfehlern:
In file included from src/test_string_vector.cc:5:0:
/usr/include/boost/container/scoped_allocator.hpp: In instantiation of ‘boost::container::container_detail::scoped_allocator_adaptor_base<OuterAlloc>::scoped_allocator_adaptor_base() [with OuterAlloc = boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]’:
/usr/include/boost/container/scoped_allocator.hpp:963:7: required from ‘boost::container::scoped_allocator_adaptor<OuterAlloc, InnerAllocs>::scoped_allocator_adaptor() [with OuterAlloc = boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >; InnerAllocs = {}]’
/usr/include/boost/container/vector.hpp:1174:15: required from ‘void boost::container::vector<T, Allocator>::assign(FwdIt, FwdIt, typename boost::container::container_detail::enable_if_c<((! boost::container::container_detail::is_convertible<InIt, typename boost::container::allocator_traits<Allocator>::size_type>::value) && ((! boost::container::container_detail::is_input_iterator<InIt>::value) && (! boost::move_detail::is_same<typename boost::container::container_detail::version<Allocator>::type, boost::container::container_detail::integral_constant<unsigned int, 0u> >::value)))>::type*) [with FwdIt = boost::container::container_detail::vec_iterator<generic::String<std::allocator<void> >*, true>; T = generic::String<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >; Allocator = boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<generic::String<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; typename boost::container::container_detail::enable_if_c<((! boost::container::container_detail::is_convertible<InIt, typename boost::container::allocator_traits<Allocator>::size_type>::value) && ((! boost::container::container_detail::is_input_iterator<InIt>::value) && (! boost::move_detail::is_same<typename boost::container::container_detail::version<Allocator>::type, boost::container::container_detail::integral_constant<unsigned int, 0u> >::value)))>::type = void]’
/usr/include/boost/container/vector.hpp:864:7: required from ‘boost::container::vector<T, Allocator>::vector(InIt, InIt, const allocator_type&) [with InIt = boost::container::container_detail::vec_iterator<generic::String<std::allocator<void> >*, true>; T = generic::String<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >; Allocator = boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<generic::String<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; boost::container::vector<T, Allocator>::allocator_type = boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<generic::String<boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >]’
src/test_string_vector.cc:78:65: required from ‘generic::StringVector<Alloc>::StringVector(const generic::StringVector<OtherAlloc>&, Alloc) [with OtherAlloc = std::allocator<void>; Alloc = boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >]’
src/test_string_vector.cc:151:46: required from here
/usr/include/boost/container/scoped_allocator.hpp:762:7: error: no matching function for call to ‘boost::interprocess::allocator<void, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >::allocator()’
{}
^
In file included from /usr/include/boost/interprocess/segment_manager.hpp:38:0,
from /usr/include/boost/interprocess/detail/managed_memory_impl.hpp:30,
from /usr/include/boost/interprocess/managed_shared_memory.hpp:25,
from src/test_string_vector.cc:1:
/usr/include/boost/interprocess/allocators/allocator.hpp:142:4: note: candidate: template<class T2> boost::interprocess::allocator<T, SegmentManager>::allocator(const boost::interprocess::allocator<T2, SegmentManager>&)
allocator(const allocator<T2, SegmentManager> &other)
^
/usr/include/boost/interprocess/allocators/allocator.hpp:142:4: note: template argument deduction/substitution failed:
In file included from src/test_string_vector.cc:5:0:
/usr/include/boost/container/scoped_allocator.hpp:762:7: note: candidate expects 1 argument, 0 provided
{}
^
In file included from /usr/include/boost/interprocess/segment_manager.hpp:38:0,
from /usr/include/boost/interprocess/detail/managed_memory_impl.hpp:30,
from /usr/include/boost/interprocess/managed_shared_memory.hpp:25,
from src/test_string_vector.cc:1:
/usr/include/boost/interprocess/allocators/allocator.hpp:136:4: note: candidate: boost::interprocess::allocator<T, SegmentManager>::allocator(const boost::interprocess::allocator<T, SegmentManager>&) [with T = void; SegmentManager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>]
allocator(const allocator &other)
^
/usr/include/boost/interprocess/allocators/allocator.hpp:136:4: note: candidate expects 1 argument, 0 provided
/usr/include/boost/interprocess/allocators/allocator.hpp:131:4: note: candidate: boost::interprocess::allocator<T, SegmentManager>::allocator(boost::interprocess::allocator<T, SegmentManager>::segment_manager*) [with T = void; SegmentManager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>; boost::interprocess::allocator<T, SegmentManager>::segment_manager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>]
allocator(segment_manager *segment_mngr)
^
/usr/include/boost/interprocess/allocators/allocator.hpp:131:4: note: candidate expects 1 argument, 0 provided
Makefile:16: recipe for target 'obj/test_string_vector.o' failed
make: *** [obj/test_string_vector.o] Error 1
ja. Ich habe eine Notwendigkeit, wo mein Code sowohl im Heapspeicher als auch im Shared-Memory-Speichersystem funktionieren muss. Daher versuche ich grundlegende Datenstrukturen zu finden, die mir dies ermöglichen. Danke, dass du dir die Zeit genommen hast. –
Keine Sorge, ich habe Ihren generischen Code leicht neu berechnet, es kompiliert es läuft. –
Das ist großartig. Vielen Dank. Ein letzter Gefallen. Könnten Sie bitte erläutern, was Sie im StringVector-Kopierkonstruktor getan haben? Was du getan hast, erscheint mir wie schwarze Magie. :) –