views:

152

answers:

2

I have a quick question about encapsulating specific types with typedef. Say I have a class Foo whose constructor takes a certain value, but I want to hide the specific type using typedef:

class Foo {
public:
  typedef boost::shared_ptr< std::vector<int> > value_type;  
  Foo(value_type val) : val_(val) {}
private:
  value_type val_;
};

But in this case, the main function still has to know the type (so it's explicitly using std::vector<int>):

int main() {
  Foo::value_type val(new std::vector<int>());
  val->push_back(123);
  Foo foo(val);
  return 0;
}

How can I fix that while still avoiding a deep copy of the vector in the Foo constructor?

+6  A: 

Various solutions:

Foo::value_type val(new Foo::value_type::element_type());
// least change from your current code, might be too verbose or too
// coupled to boost's smart pointer library, depending on your needs

Foo::value_type val(new Foo::element_type());
// add this typedef to Foo: typedef value_type::element_type element_type;

Foo::value_type val = Foo::new_value_type();
// static method in Foo, allows you to even easily change from new (as you
// encapsulate the whole smart pointer, and can specify another deleter to the
// boost::shared_ptr)

struct Foo {
  static value_type new_value_type() { // function used above
    return value_type(new value_type::element_type());
  }
};

However, if all you want is to have a vector member in Foo initialized from outside data without copying it, instead of actually sharing through a shared_ptr, then I wouldn't use a shared_ptr at all. Take a reference in Foo's ctor and document that it changes the object.

struct Foo {
  typedef std::vector<int> value_type;
  explicit Foo(value_type& val) {
    using std::swap;
    swap(val, _val);
  }

private:
  value_type _val;
};

int main() {
  Foo::value_type val;
  val->push_back(123);
  Foo foo(val);
  return 0;
}
Roger Pate
Thanks, especially the `swap()` operation is exactly what I need.
Frank
+1  A: 

There is no deep copy in the provided example. The shared_ptr is copied, but there is only one vector created. You can confirm this by calling push_back a second time after the Foo constructor and noticing that Foo.val_ also changes.

Dan McCormick
That is a misunderstanding. I meant I want to fix the typedef issue, but without introducing deep copying. (`shared_ptr` was used to avoid the copy in the first place.) I changed the text to be clearer about that.
Frank