code_junkie

Better Way To Use C++ Named Parameter Idiom?

Nov 11th, 2011
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.76 KB | None | 0 0
  1. template <class T>
  2. class _sharedWindowOpts: public detail::_baseCreateWindowOpts {
  3. public: ///////////////////////////////////////////////////////////////
  4. // No required parameters in this case.
  5. _sharedWindowOpts() { };
  6.  
  7. typedef T optType;
  8.  
  9. // Commonly used options
  10. optType& at(int x, int y) { mX=x; mY=y; return static_cast<optType&>(*this); }; // Where to put the upper-left corner of the window; if not specified, the system sets it to a default position
  11. optType& at(int x, int y, int width, int height) { mX=x; mY=y; mWidth=width; mHeight=height; return static_cast<optType&>(*this); }; // Sets the position and size of the window in a single call
  12. optType& background(HBRUSH b) { mBackground=b; return static_cast<optType&>(*this); }; // Sets the default background to this brush
  13. optType& background(INT_PTR b) { mBackground=HBRUSH(b+1); return static_cast<optType&>(*this); }; // Sets the default background to one of the COLOR_* colors; defaults to COLOR_WINDOW
  14. optType& cursor(HCURSOR c) { mCursor=c; return static_cast<optType&>(*this); }; // Sets the default mouse cursor for this window; defaults to the standard arrow
  15. optType& hidden() { mStyle&=~WS_VISIBLE; return static_cast<optType&>(*this); }; // Windows are visible by default
  16. optType& icon(HICON iconLarge, HICON iconSmall=0) { mIcon=iconLarge; mSmallIcon=iconSmall; return static_cast<optType&>(*this); }; // Specifies the icon, and optionally a small icon
  17. // ...Many others removed...
  18. };
  19.  
  20. template <class T>
  21. class _createWindowOpts: public _sharedWindowOpts<T> {
  22. public: ///////////////////////////////////////////////////////////////
  23. _createWindowOpts() { };
  24.  
  25. // These can't be used with child windows, or aren't needed
  26. optType& menu(HMENU m) { mMenuOrId=m; return static_cast<optType&>(*this); }; // Gives the window a menu
  27. optType& owner(HWND hwnd) { mParentOrOwner=hwnd; return static_cast<optType&>(*this); }; // Sets the optional parent/owner
  28. };
  29.  
  30. class createWindowOpts: public _createWindowOpts<createWindowOpts> {
  31. public: ///////////////////////////////////////////////////////////////
  32. createWindowOpts() { };
  33. };
  34.  
  35. template <class T>
  36. class _sharedWindowOpts: public detail::_baseCreateWindowOpts {
  37.  
  38. protected: // (protected so the inheriting classes may also use it)
  39.  
  40. T & me() { return static_cast<T&>(*this); } // !
  41.  
  42. public:
  43. // No required parameters in this case.
  44. _sharedWindowOpts() { };
  45.  
  46. typedef T optType;
  47.  
  48. // Commonly used options
  49. optType& at(int x, int y) { mX=x; mY=y; return me(); }; // !
  50. // ...
  51. };
  52.  
  53. class sharedWindowOpts
  54. {
  55. public:
  56.  
  57. sharedWindowOpts() {};
  58.  
  59. // Commonly used options
  60. template <class optType>
  61. static optType& at(int x, int y, optType& opts) { opts.mX=x; opts.mY=y; return opts; };
  62.  
  63. template <class optType>
  64. static optType& background(HBRUSH b, optType& opts) { opts.mBackground=b; return opts; };
  65.  
  66. // etc...
  67. }
  68.  
  69. class createWindowOpts : public sharedWindowOpts
  70. {
  71. public:
  72. createWindowOpts() : sharedwindowOpts() {};
  73.  
  74. // These can't be used with child windows, or aren't needed
  75. template <class optType>
  76. static optType& menu(HMENU m, optType& opts) { opts.mMenuOrId=m; return opts; };
  77.  
  78. template <class optType>
  79. static optType& owner(HWND hwnd, optType& opts) { opts.mParentOrOwner=hwnd; return opts; };
  80. }
  81.  
  82. CreateWindow( createWindowOpts::owner(hwnd,
  83. createWindowOpts::at(0, 100, // can use createWindowOpts because it doesn't hide sharedWindowsOpts::at
  84. createWindowOpts::menu(hmenu, createWindowOpts() ) ) ) );
  85.  
  86. //////// Base..
  87.  
  88. template<typename DerivedBuilder, typename Options>
  89. class Builder
  90. {
  91. protected:
  92. Builder() {}
  93. DerivedBuilder& me() { return *static_cast<DerivedBuilder*>(this); }
  94.  
  95. Options options;
  96. };
  97.  
  98.  
  99. ////////////////////////// A //////////////////////////
  100.  
  101.  
  102. class Options_A
  103. {
  104. public:
  105. Options_A() : a(7) {}
  106. int a;
  107. };
  108.  
  109. class Builder_A;
  110.  
  111. class A
  112. {
  113. public:
  114. virtual ~A() {}
  115. virtual void print() { cout << "Class A, a:" << a << endl; }
  116.  
  117. protected:
  118. friend class Builder_A;
  119. A(const Options_A& options) : a(options.a) {}
  120. int a;
  121. };
  122.  
  123.  
  124.  
  125. template<typename DerivedBuilder, typename Options = Options_A>
  126. class BuilderT_A : public Builder<DerivedBuilder, Options>
  127. {
  128. public:
  129. using Builder<DerivedBuilder, Options>::options;
  130. using Builder<DerivedBuilder, Options>::me;
  131. DerivedBuilder& a(int p) { options.a = p; return me(); }
  132. };
  133.  
  134.  
  135. class Builder_A : public BuilderT_A<Builder_A>
  136. {
  137. public:
  138. shared_ptr<A> create()
  139. {
  140. shared_ptr<A> obj(new A(options));
  141. return obj;
  142. }
  143. };
  144.  
  145. ////////////////////////// B //////////////////////////
  146.  
  147.  
  148.  
  149. class Options_B : public Options_A
  150. {
  151. public:
  152. Options_B() : b(8) {}
  153. int b;
  154. };
  155.  
  156. class Builder_B;
  157.  
  158. class B : public A
  159. {
  160. public:
  161. virtual ~B() {}
  162. virtual void print() { cout << "Class B, a:" << a << ", b:" << b << endl; }
  163.  
  164. protected:
  165. friend class Builder_B;
  166. B(const Options_B& options) : A(options), b(options.b) {}
  167. int b;
  168. };
  169.  
  170.  
  171. template<typename DerivedBuilder, typename Options = Options_B>
  172. class BuilderT_B : public BuilderT_A<DerivedBuilder, Options>
  173. {
  174. public:
  175. using Builder<DerivedBuilder, Options>::options;
  176. using Builder<DerivedBuilder, Options>::me;
  177. DerivedBuilder& b(int p) { options.b = p; return me(); }
  178. };
  179.  
  180.  
  181. class Builder_B : public BuilderT_B<Builder_B>
  182. {
  183. public:
  184. shared_ptr<B> create()
  185. {
  186. shared_ptr<B> obj(new B(options));
  187. return obj;
  188. }
  189. };
  190.  
  191.  
  192.  
  193. ////////////////////////// C //////////////////////////
  194.  
  195.  
  196.  
  197. class Options_C : public Options_B
  198. {
  199. public:
  200. Options_C() : c(9) {}
  201. int c;
  202. };
  203.  
  204. class Builder_C;
  205.  
  206. class C : public B
  207. {
  208. public:
  209. virtual ~C() {}
  210. virtual void print() { cout << "Class C, a:" << a << ", b:" << b << ", c:" << c << endl; }
  211.  
  212. protected:
  213. friend class Builder_C;
  214. C(const Options_C& options) : B(options), c(options.c) {}
  215. int c;
  216. };
  217.  
  218.  
  219. template<typename DerivedBuilder, typename Options = Options_C>
  220. class BuilderT_C : public BuilderT_B<DerivedBuilder, Options_C>
  221. {
  222. public:
  223. using Builder<DerivedBuilder, Options>::options;
  224. using Builder<DerivedBuilder, Options>::me;
  225. DerivedBuilder& c(int p) { options.c = p; return *static_cast<DerivedBuilder*>(this); }
  226. };
  227.  
  228.  
  229. class Builder_C : public BuilderT_C<Builder_C>
  230. {
  231. public:
  232. shared_ptr<C> create()
  233. {
  234. shared_ptr<C> obj(new C(options));
  235. return obj;
  236. }
  237. };
  238.  
  239.  
  240.  
  241.  
  242.  
  243. ///////////////////////////////////////////////////////////////////////////
  244.  
  245.  
  246. int main()
  247. {
  248. shared_ptr<A> a = Builder_A().a(55).a(1).create();
  249. a->print();
  250.  
  251. shared_ptr<B> b = Builder_B().b(99).b(2).a(88).b(4).a(2).b(3).create();
  252. b->print();
  253.  
  254. shared_ptr<C> c = Builder_C().a(99).b(98).c(97).a(96).c(6).b(5).a(4).create();
  255. c->print();
  256.  
  257. return 0;
  258. }
  259.  
  260. /* Output:
  261.  
  262. Class A, a:1
  263. Class B, a:2, b:3
  264. Class C, a:4, b:5, c:6
  265.  
  266. */
Add Comment
Please, Sign In to add comment