tags:

views:

308

answers:

3

I am using the pimpl idiom and want to reference one of the methods of the forward declared class. Below isn't exactly what I'm doing but uses the same concepts.

template< typename Class, void (Class::*Method)(void) >
struct Call
{
   Call( Class* c )
    : m_c(c)
   { }

   void operator()( void )
   {
      (m_c->*Method)();
   }

   Class* m_c;
};

class A
{
public:
   void foo( void )
   {
      std::cout << "A::foo\n";
   }
};

// this works
void do_foo( A* a )
{
   Call<A,&A::foo> c(a);
   c();
}

class B;
// this doesn't compile
extern void B::bar( void );

// this is what i'd ultimately like to do
void do_bar( B* b )
{
   Call<B,&B::bar> c(b);
   c();
}

Two questions:

  • Can this be done?
  • Why can't it be done?
A: 

It can't compile B::bar() because class B is undefined. But I think you are leaving too much out of the question. At this point:

void do_bar( B* b )
{
   Call<B,&B::bar> c(b);
   c();
}

why can't you just say?

void do_Bar(B* b) {
    b->bar();
}

Perhaps if you included that explanation it would be easier to answer your question.

Second, why is this needed when (as seen above) you want to call it through do_bar()? Why not make do_bar the extern?

extern void B::bar( void );
jmucchiello
A: 

I don't know, pimpl classes are usually tightly bound to their encapsulating class. I think it's a bit of a smell to have it any other way. Which is why I usually leave it as an inner class:

class A
{
public:
    ...
private:

    ...

    class A_impl;
    boost::scoped_ptr<A_impl> impl;
};
billybob
+1  A: 

You cannot forward declare a member function. I think the reason is that, when you call the function on a pointer to B, the compiler has to pass the this pointer to that method. But it doesn't know the precise class hierarchy of B yet. So possible adjustments of that pointer (due to the method being virtual, for example) would not be possible at that point. The compiler would also not know what visibility that method has. After all, it could be private and you are not allowed to call it from outside. The only way to declare that member function is to define the class, and then declare the function within that definition. Another way to solve your problem is to declare your free function instead:

class B;
void do_bar( B* b );

Then define do_bar in a file in which you can safely include the definition of the class B.

Johannes Schaub - litb