From: Fejimush on
What are good strategies for selecting, either at run-time or compile
time, various pimpl'ed implementations? Also, retaining the ability
to switch implementations without recompiling.

Boost has an example but with only one implementation class: (what
would an example with 2 implementation classes look like?)
http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html#pimpl

The pimpl'ed class cpp file has to include at least one implementation
header file. Is there a method to avoid changing that included header
when switching implementations?

Or, are we using the pimpl idiom incorrectly?

thanks,
graham

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Tony Delroy on
On Apr 17, 2:36 am, Fejimush <grahamre...(a)gmail.com> wrote:
> What are good strategies for selecting, either at run-time or compile
> time, various pimpl'ed implementations? Also, retaining the ability
> to switch implementations without recompiling.
>
> Boost has an example but with only one implementation class: (what
> would an example with 2 implementation classes look like?)http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.htm...
>
> The pimpl'ed class cpp file has to include at least one implementation
> header file. Is there a method to avoid changing that included header
> when switching implementations?
>
> Or, are we using the pimpl idiom incorrectly?

Hi Graham,

I think you're a little confused about the pimpl idiom. Its purpose
is to allow users of a class to know that the class will contain space
for a pointer to an implementation class, without having to know
anything about the contents of the implementation class. This allows
the implementation data to be varied without requiring recompilation
of the clients. It is not intended as a method for switching between
concurrently maintained implementations - rather it allows one
implementation to be maintained (i.e. updated) while limiting the
recompilation needed.

To switch between multiple implementations of a class, you can employ
other techniques: e.g. run-time polymorphism (virtual dispatch),
pointers to functions, the humble if statement etc; or compile time
#ifdefs (change via compiler switch), templates, typedefs (facilitate
centralised choice between implementations, i.e. one line code
changes).... As run-time switching is the more general of your
requests (compile time is simply a performance improvement thereto) I
suggest you start by read ing about the "virtual" keyword and OO
techniques.

Cheers,

Tony

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carl Barron on
In article
<38f73473-466e-4baf-8358-add3121b2ae0(a)c65g2000hsa.googlegroups.com>,
Fejimush <grahamreitz(a)gmail.com> wrote:

> What are good strategies for selecting, either at run-time or compile
> time, various pimpl'ed implementations? Also, retaining the ability
> to switch implementations without recompiling.
>
without recompiling most likely runtime polymorhism. If you don't
want to add classes derived from the base at will the fact they are all
derived from a common base can also be hidden by not exposing them
to users. If you need to add pimples at will, I think its a design
problem. If you have two or three policies to be choosen at run time
provide a function boost::shared_ptr<Pimpl> create_pimple(/* some arg
to say which */); hidden from user and use it to get the proper derived
class ptr in the shared_ptr<Pimple> I don't see the problem,
// foo header foo.hpp
#include <boost/shared_ptr.hpp>
class Foo
{
class Pimpl;
boost::shared_ptr<Pimpl> pimpl;
public:
explicit Foo(int n=1);
void something();
// ...
};
// implementation
#include "foo.hpp"
struct Foo::Pimple
{
// base class with virt funcs.
};

namespace
{
struct Pimpl_1:Pimpl { /**/};
struct Pimpl_2:Pimpl {/**/};
// ,,,
}

Foo:Foo(int n)
{
switch(n)
{
case 1:pimpl = boost::shared_ptr<Pimpl_1>(new Pimp_1); break;
case 2:pimpl = boost::shared_ptr<Pimpl_2>(new Pimpl_2);break;
// ...
default:pimpl = boost::shared_ptr<Pimpl_1>(new Pimpl_1); break;
}
};

void Foo::something()
{
access data thru pimpl's virt. funcs.
}
// ...

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Fejimush on
Thanks for the help, although I didn't do a good job articulating my
initial question. My first sentence was completely mis-stated
(sorry). Let me try again.

We are working with an embedded device where only one implementation
of the driver needs to be in memory at any moment in time. The
implementation may vary due to variations in the hardware (this must
be a common issue). The pimpl idiom seemed to fit the bill.

My question is, what strategies can we use to get the correct
implementation at load (link) time (not run time or compile time) to
select the desired implementation?

There are several variations of the handle body idiom, including the
bridge pattern and pimpl patterns which may work. We didn't find any
clear examples of the pimpl idiom showing how and when to choose an
implementation.

thanks,
graham

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carl Barron on
In article
<27615ebc-fbc4-4530-897e-89aa1741eb20(a)m3g2000hsc.googlegroups.com>,
Fejimush <grahamreitz(a)gmail.com> wrote:

> Thanks for the help, although I didn't do a good job articulating my
> initial question. My first sentence was completely mis-stated
> (sorry). Let me try again.
>
> We are working with an embedded device where only one implementation
> of the driver needs to be in memory at any moment in time. The
> implementation may vary due to variations in the hardware (this must
> be a common issue). The pimpl idiom seemed to fit the bill.
>
> My question is, what strategies can we use to get the correct
> implementation at load (link) time (not run time or compile time) to
> select the desired implementation?
>
> There are several variations of the handle body idiom, including the
> bridge pattern and pimpl patterns which may work. We didn't find any
> clear examples of the pimpl idiom showing how and when to choose an
> implementation.
>
Pimple is to hide implementation details so they can be modifed
without recompiling client code. Here you want a to select one of
k implementaions of a classes Driver and change them some how.

None of the classical OOP Patterns are done at link time, they are done
at runtime. If you use templates those used must be visiable at
compile time, and they solve a similiar problem at compile time.

the only link time solution is k complied objects and selecting the
right one in your build processsing by some means beyound standard C++.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]