1

Suppose I'm given a class A. I would like to wrap pointers to it into a small class B, some kind of smart pointer, with the constraint that a B* is automatically converted to an A* so that I don't need to rewrite the code that already uses A*.

I would therefore want to modify B so that the following compiles...

struct A {
  void foo() {}
};

template <class K>
struct B {
  B(K* k) : _k(k) {}
  //operator K*() {return _k;}
  //K* operator->() {return _k;}
private:
  K* _k;
};

void doSomething(A*) {}

void test() {
  A a;
  A* pointer_to_a (&a);
  B<A> b (pointer_to_a);
  //b->foo();             // I don't need those two...
  //doSomething(b);

  B<A>* pointer_to_b (&b);

  // Following represents existing code I don't want to change...
  pointer_to_b->foo();       // 'foo' : is not a member of 'B<K>'
  doSomething(pointer_to_b); // 'doSomething' : cannot convert parameter 1 from 'B<K> *' to 'A *'
}

Note that B inheriting from A is not an option (instances of A are created in factories out of my control)...

Is it possible?

Thanks.

4

6 回答 6

3

The type of pointer_to_b is pointer to B, which is a type you cannot modify; it's implemented by the compiler.

You can do (*pointer_to_b)->foo(), which will do the right thing (assuming you have the overridden operator->()). However, that won't let the other code do the right thing, if you pass pointer_to_be into it.

Also let me add that you can override operator& on B to return an A*, which might solve your problem, depending on the specific use cases.

于 2010-04-26T17:15:45.933 回答
2

What about function get() as in boost::shared_ptr?

template <class K>
struct B {
  B(K* k) : _k(k) {}
  K* get() { return _k;}
private:
  K* _k;
};

Then you could use it as follows:

pointer_to_b->get()->foo();      
doSomething(pointer_to_b->get());
于 2010-04-26T17:18:18.017 回答
0

The operators you have commented out in your struct B look like they should make it do what you want... why are they commented out? Does it not work when they're uncommented, and if not, can you post the errors?

于 2010-04-26T17:21:52.793 回答
0

If I recall the way shared_ptr gets around the issue I think you have is that you never pass around a shared_ptr*, you pass around a shared_ptr object. That way the operator-> works because it is being called on the object, not the pointer to the object. I recommend that you pass around B<A> instead of B<A>*. Who cares if the wrapper class is a pointer or not, as long as it represents a pointer to A it shouldn't matter.

于 2010-04-26T17:45:32.393 回答
0

B inheriting from A is an option, this compiles (VS 2008 at least):

struct A { 
  void foo() {} 
}; 

template <typename  T> 
struct B : T
{ 
  B(const T& t) : T(t) 
  {} 
}; 

void doSomething(A*) {} 

void test() { 
  A a; 
  B<A> b (a); 

  B<A>* pointer_to_b (&b); 

  // Following represents existing code I don't want to change... 
  pointer_to_b->foo();       
  doSomething(pointer_to_b); 
}
于 2010-04-26T19:01:13.967 回答
0

This should work from my point of view

struct A {
  void foo() {}
};

template <class K>
struct B {
  B(K* k) : _k(k) {}
  operator K*() {return _k;}
  K* operator->() {return _k;}
private:
  K* _k;
};

void doSomething(A*) {}

void test() {
  A a;
  A* pointer_to_a (&a);
  B<A> pointer_to_b (pointer_to_a);

  // Following represents existing code NOT CHANGED
  pointer_to_b->foo();       
  doSomething(pointer_to_b);

}
于 2010-04-26T19:51:10.213 回答