3

I have the following structure:

class A { A(const A&) {...} virtual int member() = 0; virtual ~A() {}; } class B : public A { virtual int member(){... } virtual ~B(){} } class C : public A { virtual int member(){... } virtual ~C(){} } 

And use std::shared_ptr<A> as return type of my factory.

std::shared_prt<A> Factory::get(params...) { ... return std::make_shared<B>(params); } std::shared_ptr<A> Aptr = Factory::get(params...) 

Now I try to pass it to an external method:

boost::iostreams::filtering_istream void push( const T& t, std::streamsize buffer_size = default value, std::streamsize pback_size = default value ); 

this call fails at compile time because some_external_function tries to call the pure member() of A and not of B.

concept_adapter.hpp:122: Error:cannot declare field 'boost::iostreams::detail::concept_adapter::t_' to be of abstract type 'A'

9
  • 4
    What is the prototype of some_external_function? Does it get parameter by value? You should get it either by reference or pointer if you want polymorphism to work. Commented Dec 4, 2013 at 14:05
  • 2
    How and when does it fail? Compile time? Run time? Please provide more details, including compiler errors/warnings (if there are any) or debugger backtraces. Commented Dec 4, 2013 at 14:14
  • @JonathanWakely, yes you're right, I removed my comment Commented Dec 4, 2013 at 14:32
  • Without the declaration of some_external_function and the exact details of the failure this question is off-topic and should be closed, please provide the information requested by Joachim Pileborg in the comment above. Commented Dec 4, 2013 at 14:33
  • 1
    The error message does not support your statement that "some_external_function tries to call the pure member() of A". It would appear that A does not satisfy a requirement of the Boost code to which you are passing it - most like copy constructibility. Indeed, the documentation of boost::iostreams::filtering_istream::push requires the first argument to be CopyConstructible. Commented Dec 4, 2013 at 22:21

1 Answer 1

2

You have to use the PImpl idiom here.

The push method requires that the first argument is copy constructible. Which means that it is copied somewhere deep inside the guts of Boost. No good, because you cannot copy a polymorphic object, it will be sliced.

The solution is to have a non-polymorphic class APimpl that holds a pointer (shared, unique or raw, you decide) to A, and forwards calls to that pointer. It can be copied freely with no ill effects of slicing.

class APimpl { public: APimpl(std::shared_ptr<A> a) : p_a(a) {} // compiler-generated copy ctor and assignment are OK here void method() { p_a->method(); } private: std::shared_ptr<A> p_a; }; 

You may need to have a clone method in A and use it when copying APimpl, or have an A shared between many instances of APimpl. Which one you want depends on what A does. My example demonstrates the second case.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.