2

I'm wondering why the following code does NOT work. The main idea behind it is as follows:

  1. I want to use my custom classes that inherits by std allocator and boost::interprocess::allocator respectively and I want to use them instead of the base allocators
  2. When I create a class MyStdAllocator, which inherits by std::allocator and use it instead of std::allocator (see variables x1 and x2) it works and gives no warning and no errors.
  3. When I create a class MyBoostAllocator, which inherits by boost::interprocess::allocator and use it instead of boost::interprocess:allocator (see variables y1 and y2) it does NOT work and gives me compilation errors listed on the bottom of this question.

Clould you please tell me, why such inheritance does not work and how to fix it?

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <iostream>

using namespace boost::interprocess;


template <typename _Tp>
class MyStdAllocator : public std::allocator<_Tp>
{
};


template<class T, class SegmentManager>
class MyBoostAllocator : public allocator<T, SegmentManager>
{
};



typedef std::allocator<int> std_allocator;
typedef MyStdAllocator<int> my_std_allocator;

typedef allocator       <int, managed_shared_memory::segment_manager> boost_allocator;
typedef MyBoostAllocator<int, managed_shared_memory::segment_manager> my_boost_allocator;


int main(int argc, char** argv) {

    struct shm_remove {
        shm_remove() {
            shared_memory_object::remove("MySharedMemory");
        }

        ~shm_remove() {
            shared_memory_object::remove("MySharedMemory");
        }
    } remover;

    managed_shared_memory segment(create_only,
            "MySharedMemory", //segment name
            65536);

    //Create an allocator that allocates ints from the managed segment
    allocator<int, managed_shared_memory::segment_manager>
            allocator_instance(segment.get_segment_manager());


    std_allocator *x1;
    x1 = new std_allocator();
    delete x1;

    my_std_allocator *x2;
    x2 = new my_std_allocator();
    delete x2;


    boost_allocator *y1;
    y1 = new boost_allocator(segment.get_segment_manager());
    delete y1;

    // following lines generate compilation errors:
    my_boost_allocator *y2;
    y2 = new my_boost_allocator(segment.get_segment_manager());
    delete y2;

    std::cout<<"its working!\n";

    return 0;

}

The compilation error is as follows:

../src/test.cpp:73:59: error: no matching function for call to ‘MyBoostAllocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >::MyBoostAllocator(boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index, 16ul>::segment_manager*)’
../src/test.cpp:73:59: note: candidates are:
../src/test.cpp:24:7: note: MyBoostAllocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >::MyBoostAllocator()
../src/test.cpp:24:7: note:   candidate expects 0 arguments, 1 provided
../src/test.cpp:24:7: note: MyBoostAllocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >::MyBoostAllocator(const MyBoostAllocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >&)
../src/test.cpp:24:7: note:   no known conversion for argument 1 from ‘boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index, 16ul>::segment_manager* {aka boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index>*}’ to ‘const MyBoostAllocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >&’
make: *** [src/test.o] Error 1
Wojciech Danilo
  • 11,573
  • 17
  • 66
  • 132
  • 1
    Well, as the error says, your allocator class doesn't have a constructor that matches your initialiser. – Kerrek SB Oct 24 '12 at 14:29
  • Ok, but why the constructor is not inherited automatically? is it even possible to inherit it with C++ when inheriting by base class, that provides such constructor? – Wojciech Danilo Oct 24 '12 at 14:30
  • 1
    @danilo2 Constructors are not inherited in C++ (or any other language I know of). – user1610015 Oct 24 '12 at 14:47
  • Thank you, I was wrong with this one. But I found this site: http://stackoverflow.com/questions/5411229/c0x-inherited-constructor-in-templates (I'm using C++0x), but when I try to add line: using allocator::allocator; (as suggested on this site) it still gives compilation error, but this time: "‘boost::interprocess::allocator::allocator’ names constructor make: *** [src/alien.o] Error 1". It should work, doesnt it? – Wojciech Danilo Oct 24 '12 at 14:53

1 Answers1

1

This seems to be a "supported C++11" question. See

http://wiki.apache.org/stdcxx/C++0xCompilerSupport

for which compilers support which features.

Inheriting constructors is gnu4.8+ only.

When they are you still have to explicitly put in a using construct.

template<class T, class SegmentManager> 
class MyBoostAllocator : public allocator<T, SegmentManager> 
{ 
 public:
     using allocator<T, SegmentManager >::allocator;
};  

Until that is available, write the constructors in your derived class.

CashCow
  • 30,981
  • 5
  • 61
  • 92