// Copyright David Abrahams 2003. Use, modification and distribution is // subject to the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include namespace test { namespace mpl = boost::mpl; struct named_base {}; template struct named : named_base { typedef KW key_type; typedef T value_type; named(T& x) : value(x) {} template T& get( Default const& ) const { return value; } T& get() const { return value; } T& value; }; template struct keyword { template named operator=(T& x) const { return named(x); } template named operator=(T const& x) const { return named(x); } }; // // Add labels to arguments that may have been passed positionally. // Why the help with function ordering is required is completely // beyond me. // template named label_positional_arg(T const& x, ...) { return named(x); } template named label_positional_arg(T& x, char) { return named(x); } template named const& label_positional_arg(named const& x, int) { return x; } // A tuple of labeled argument holders template struct list : H, T { list(H h, T t) : H(h), T(t) {} template struct apply : mpl::apply_if< boost::is_same , mpl::identity , typename T::template apply > {}; template typename apply::type const& value(K) const { return boost::implicit_cast< typename apply::type const& >(*this); } }; template list cons(H const& h, T const& t) { return list(h,t); } struct nil { template struct apply { typedef nil type; }; template static D const& get(D const& x) { return x; } template nil const& value(D const& x) const { return *this; } }; // ------------ end of named param library code ------------- // // keyword declarations. PP generatable, of course // struct name_t : keyword { using keyword::operator=; } name; struct value_t : keyword { using keyword::operator=; } value; struct index_t : keyword { using keyword::operator=; } index; // // core function implementation // template int f_impl(Params const& p) { std::cout << "-------- f --------" << std::endl; std::cout << "name = " << p.value(name).get("unnamed") << std::endl; std::cout << "value = " << p.value(value).get(666.222) << std::endl; std::cout << "index = " << p.value(index).get(999) << std::endl; return 1; } // // f overloads for various #s of args. This could be avoided somewhat // by using f((kw1 = v1, kw2 = v2)) and overloading operator, but // there would be other disadvantages, like an inability to handle two // initial positional args. This boilerplate can probably be // generated with the PP. // // Some reduction might be achieved by successively currying single // arguments and calling the next overload, if the cons lists were // built backwards. // int f() { return f_impl(nil()); } template int f(Name const& name) { return f_impl( cons( label_positional_arg(name, 0) , nil() )); } template int f(Name const& name, Value const& value) { return f_impl( cons( label_positional_arg(name, 0) , cons( label_positional_arg(value, 0) , nil() ))); } template int f(Name const& name, Value const& value, Index const& index) { return f_impl( cons( label_positional_arg(name, 0) , cons( label_positional_arg(value, 0) , cons( label_positional_arg(index, 0) , nil() )))); } // // Just like f, but no default for name // template int g_impl(Params const& p) { std::cout << "-------- g --------" << std::endl; // name has no default std::cout << "name = " << p.value(name).get() << std::endl; std::cout << "value = " << p.value(value).get(666.222) << std::endl; std::cout << "index = " << p.value(index).get(999) << std::endl; return 1; } template int g(Name const& name) { return g_impl( cons( label_positional_arg(name, 0) , nil() )); } template int g(Name const& name, Value const& value) { return g_impl( cons( label_positional_arg(name, 0) , cons( label_positional_arg(value, 0) , nil() ))); } template int g(Name const& name, Value const& value, Index const& index) { return g_impl( cons( label_positional_arg(name, 0) , cons( label_positional_arg(value, 0) , cons( label_positional_arg(index, 0) , nil() )))); } int x1 = f("x", 3.14, 22); int x2 = f(value = 3.14, name = "x"); int x3 = f(value = 6.5); int x4 = f(); int x5 = g("x", 3.14, 22); int x6 = g(value = 3.14, name = "x"); // g has no default for name, so this call fails // int x7 = g(value = 6.5); int x8 = g("q", index = 77); } int main() { return 0; }