| 790 | This 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 | |
| 796 | template<typename MessageType> |
| 797 | void print(MessageType const &message) |
| 798 | { |
| 799 | std::cout << message << std::endl; |
| 800 | } |
| 801 | namespace 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 | } |
| 808 | namespace LanguagePolicyEnglish |
| 809 | { |
| 810 | struct tag {}; |
| 811 | template<class T> std::string message(T) |
| 812 | { |
| 813 | return "Hello, World!"; |
| 814 | } |
| 815 | } |
| 816 | namespace LanguagePolicyGerman |
| 817 | { |
| 818 | struct tag {}; |
| 819 | template<class T> std::string message(T) |
| 820 | { |
| 821 | return "Hallo Welt!"; |
| 822 | } |
| 823 | } |
| 824 | namespace LanguagePolicyDefault |
| 825 | { |
| 826 | struct tag {}; |
| 827 | using LanguagePolicyGerman::message; |
| 828 | } |
| 829 | int 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 | |
| 862 | The 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 | |