[Gauge for interest] Surrogate template

Hi all, Recently I've an surrogate/proxy pattern implemented for storing related type as value. It is based on chapter 5 of Rumination on C++ by Andrew Koenig and Barbara moo. Original version required stored object to define their own virtual copy constructor. I have updated it to template version. Besides, it also relief user from defining virtual copy constructor by moving virtual copy inside surrogate. Thanks to template constructor making this possible. Drawback: 1) Each copy construction of surrogate incurs 2 virtual calls instead of 1 in the original. 2) Object compositing surrogate that has interface taking derived class must change to template member function in order to use template constructor of surrogate. Does anybody interested to include it as boost::surrogate? Example Usage: class boy { public: virtual void tell() = 0; }; class happy_boy : public boy { ... }; class study_boy : public boy { ... }; void say_hi(boy& the_boy) { the_boy.tell(); } int main() { std::cout << "Hello boost::surrogate!" << std::endl; happy_boy Terry; study_boy Thomas; std::vector<boost::surrogate<boy> > boy_list; boy_list.push_back(boost::surrogate<boy>(Terry)); boy_list.push_back(boost::surrogate<boy>(Thomas)); std::for_each(boy_list.begin(), boy_list.end(), say_hi); std::cin.get(); } Regards, Alan Tong

On 27/02/2011 07:56, Alan sinde wrote:
Example Usage:
class boy { public: virtual void tell() = 0; };
class happy_boy : public boy { ... }; class study_boy : public boy { ... };
void say_hi(boy& the_boy) { the_boy.tell(); }
int main() { std::cout<< "Hello boost::surrogate!"<< std::endl; happy_boy Terry; study_boy Thomas;
std::vector<boost::surrogate<boy> > boy_list; boy_list.push_back(boost::surrogate<boy>(Terry)); boy_list.push_back(boost::surrogate<boy>(Thomas));
std::for_each(boy_list.begin(), boy_list.end(), say_hi);
std::cin.get(); }
How is that different from clone_ptr and other similar works?

How is that different from clone_ptr and other similar works?
surrogate does not attempts to emulate a concrete type via pointer interface. Instead, It act as drop in replacement for value type This is the main idea behind surrogate pattern. Typically, this is achieve through surrogate<T>::operator T&(). This also implies that most STL function objects can work with std::vector<boost::surrogate<T>>. Besides, It encapsulate object allocation inside itself. In my humble opinion, this feel like less error prone. boost::clone_ptr, on the other hand, emulate a concrete type via pointer interface. This implies that most STL function objects is incompatible to std::vector<boost::clone_ptr<T>>. This also apply to ordinary pointer type, boost::shared_ptr and other similar. Surrogate also differ from value_ptr by Edd Dawson. Surrogate does not need object to have virtual copy function. I have reviewed Boost.ClonePtr by Rafal Moniuszko, it seems to me pointed objects get sliced during copy construction. Could you please confirm this? In many ways, surrogate is similar to boost::clone_ptr. similar to std::stack adapt std::vector. It is possible to adapt boost::clone_ptr to surrogate or vice-versa However, their both serve different purpose as std::stack is to std::vector.

On 27/02/11 18:50, Alan sinde wrote: Typically, this is achieve through surrogate::operator T&().
This typically has a lot of really unwanted quirky side effect :/
True. Implicit conversion can be quirky. Mainly due to type safety is compromised. But it is mostly limited to implicit conversion to pointer and built-in types. Where in pointer case, user can erroneously delete or modify via returned pointers without any compilation errors and warnings. This is why std::string never provide operator char const*(). However, that doesn't defeat the role of implicit conversion in this case. In boost::surrogate<T>, its implicit interface require the wrapped objects to be derivative of T. This implies, wrapped type and T cannot be pointer or built-in type. Since surrogate::operator T&() returns reference to object, it is hard for user to apply operator delete on it. Also, it is sensible for user to write to the returned reference in this case. After all, isn't conversion to wrapped object the whole point in wrapper pattern? Regards, Alan
participants (3)
-
Alan sinde
-
Joel Falcou
-
Mathias Gaunard