Changes between Version 19 and Version 20 of BestPracticeHandbook


Ignore:
Timestamp:
May 11, 2015, 9:59:15 PM (7 years ago)
Author:
Niall Douglas
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • BestPracticeHandbook

    v19 v20  
    720720todo
    721721
    722 == 15. DESIGN: Consider making (more) use of C++ 11 namespace composure as a design pattern ==
    723 
    724 todo check this compiles
    725 
    726 https://en.wikipedia.org/wiki/Policy-based_design
    727 
    728 {{{
     722== 15. DESIGN: Consider making (more) use of ADL C++ namespace composure as a design pattern ==
     723
     724Most C++ programmers are aware of C++ template policy based design. This example is taken from https://en.wikipedia.org/wiki/Policy-based_design:
     725
     726{{{#!c++
    729727#include <iostream>
    730728#include <string>
     
    790788}}}
    791789
     790This works very well when your policy implementations fit nicely into template types, however for when they don't an ADL based namespace composure design pattern can be highly effective. Here is the same program written using namespace composure:
     791
     792{{{#!c++
     793#include <iostream>
     794#include <string>
     795
     796template<typename MessageType>
     797void print(MessageType const &message)
     798{
     799  std::cout << message << std::endl;
     800}
     801namespace HelloWorld
     802{
     803  template<class T> void run(T v)
     804  {
     805    print(message(v));  // Can't instantiate message nor print until T is known
     806  }
     807}
     808namespace LanguagePolicyEnglish
     809{
     810  struct tag {};
     811  template<class T> std::string message(T)
     812  {
     813    return "Hello, World!";
     814  }
     815}
     816namespace LanguagePolicyGerman
     817{
     818  struct tag {};
     819  template<class T> std::string message(T)
     820  {
     821    return "Hallo Welt!";
     822  }
     823}
     824namespace LanguagePolicyDefault
     825{
     826  struct tag {};
     827  using LanguagePolicyGerman::message;
     828}
     829int main()
     830{
     831  /* Example 1 */
     832  {
     833    using namespace LanguagePolicyEnglish;
     834    using namespace HelloWorld;
     835    run(tag()); // prints "Hello, World!"
     836    // This works because HelloWorld::run()'s message() resolves inside these
     837    // braces to LanguagePolicyEnglish::message() to the same namespace as
     838    // struct tag thanks to argument dependent lookup
     839  }
     840
     841  /* Example 2
     842  * Does the same, but uses another language policy */
     843  {
     844    using namespace LanguagePolicyGerman;
     845    using namespace HelloWorld;
     846    run(tag()); // prints "Hallo Welt!"
     847    // Whereas HelloWorld::run()'s message() now resolves inside these
     848    // braces to LanguagePolicyGerman::message()
     849  }
     850
     851  /* Example 3 */
     852  {
     853    using namespace LanguagePolicyDefault;
     854    using namespace HelloWorld;
     855    run(tag()); // prints "Hallo Welt!"
     856    // Tries to find message() inside namespace LanguagePolicyDefault,
     857    // which finds message aliased to LanguagePolicyGerman::message()
     858  }
     859}
     860}}}
     861
     862The above pattern is in fact entirely C++ 03 code and uses no C++ 11. However, template aliasing in C++ 11 makes the above pattern much more flexible. Have a look at https://github.com/ptal/expected/blob/master/include/boost/functional/monads/rebindable.hpp for examples of this ADL invoked namespace composure design pattern
     863
    792864== 16. BUILD: Consider defaulting to header only, but make available C++ 11 features very substantially reducing build times ==
    793865