Pimpl idiom and member function templates

P

Peteris Krumins

Hello!

I was playing around pimpl idiom and discovered that there is a problem
with it if a class member template function exists which has to access
private data, since only the forward declaration of pimpl class is
provided.


Example:


class Foo
{
private:
struct foo_impl;
foo_impl *pimpl;

public:
// ...
//

template <typename T>
T bar()
{
// bar() has to access private data which is located
// in pimpl.
// for example,

int id = pimpl->baz;

// ...
}
};

To allow the template be instantiated for any type is has to be
left in the interface of Foo class. But then it cannot access
pimpl->baz because pimpl has only been forward declared.

I have three solutions but I do not like any of them.

The first solution is to include or write the definition of
foo_impl class in the same file where Foo's interface is,
so Foo::foo_impl was defined.

I don't like because it would not reduce compile times and probably
will make client code to be recompiled since header file would have
changed since last compile and most tools for automatic compilation
look at modification times.

The second solution is to create a global function which takes
a reference to Foo and make this function a friend to Foo.

Example,
class Foo {
// ...
template <typename T>
friend int bar(Foo &foo);
// ...
};

and somewhere
template <typename T> int bar(Foo &foo) { return foo->impl->baz; }

As bar() is friend to Foo, it can access private pimpl.

I don't like this solution because i break interface of Foo, instead
of a convenient member function a global has to be added and an object
has to be passed to this function.

The third solution is the simplest, bring the particular private member
which has to be accessed in template function back to private section
of Foo.
I don't like it cause I have to expose implementation details which is
what pimpl helps me not to do.


Can anyone think of more solutions to this problem? Maybe there is
a direct solution which allows somehow to keep the original
design and access pimpl members?


Thanks!


P.Krumins
 
A

Alipha

Peteris said:
Hello!

I was playing around pimpl idiom and discovered that there is a problem
with it if a class member template function exists which has to access
private data, since only the forward declaration of pimpl class is
provided.

[snip]

if the number of possible template arguments is small, you can do
explicit template instantiation:

// .h file:

class Foo {
public:
template<class T>
void bar(T x);
};

// .cpp file:
template void Foo::bar(int);
template void Foo::bar(long);
template void Foo::bar(float);

Otherwise, you're trying to mix two things that are incompatiable:
separate compilation and templating. You COULD also get one of those
rare compilers which support the export keyword... (comeau is the only
one I know of) Of course, so much for portability in that case.
 
P

Peteris Krumins

if the number of possible template arguments is small, you can do
explicit template instantiation:

[snip]

Otherwise, you're trying to mix two things that are incompatiable:
separate compilation and templating. You COULD also get one of those
rare compilers which support the export keyword... (comeau is the only
one I know of) Of course, so much for portability in that case.

Thanks!

Unfortunately that member template function works like a factory and
I can't explicitly instantiate because I don't know all types which
will
be constructed with it.

I chose to bring one of the pimpl members back to the class to solve
the problem till more compilers start supporting export keyword!


P.Krumins
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top