Я хочу добиться того, что было достигнуто в ответе на это вопрос, но для вектора строк, т.е. строковых объектов. Я хочу иметь возможность писать общий код, который можно использовать как с памятью кучи, так и с разделяемой памятью. Я эмулировал код и написал класс для реализации вектора строк, который будет работать как с памятью кучи, так и с разделяемой памятью. У меня это работает по большей части. Однако, когда я пытаюсь инициализировать/создать общий вектор памяти строк из вектора строк, выделенного кучей, я получаю ошибки компиляции. В упомянутом выше вопросе вектор общей памяти был инициализирован из вектора общей памяти (цитируя «это работает из-за ... MAGIC!»). Не уверен, что это потому, что этот вопрос касался вектора целых чисел, которые легко копируются и перемещаются. Я предоставил конструктор копирования для класса строк с общей памятью, но он все еще не работает. Я предоставил свой код ниже (закомментировал код, который дает мне ошибки компиляции). Любая помощь приветствуется. Спасибо.
#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();
}
В том числе ошибки компиляции:
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