Boost logo

Boost :

From: David Greene (greened_at_[hidden])
Date: 2004-12-27 14:37:27


David Abrahams wrote:

>>Is there an accessible page of documentation somewhere?
>
> http://tinyurl.com/2qtkk

Thanks. Looks very cool.

> There has already been a released named_template_params.hpp in
> boost/detail "forever".
> http://www.boost.org/boost/detail/named_template_params.hpp

I know this used to be used by the old iterator_adaptors. I can't
quite remember what the interface to named_template_params was
and it's a little difficult for me to envision given just the header
file. Got an example laying around somewhere?

> IMO named template parameters are unweildy in C++. I prefer "unnamed
> template parameters" like those described in
> http://www.boost.org/libs/python/doc/v2/class.html

"Boost.Python determines the role of the argument from its type."

So does that mean that this idiom can only be used when each
argument is of a distinct type? I realize that this can be made
to happen by wrapping each argument in a unique class, but isn't
that exactly what named template parameters is?

The use of what I've got working now is shown below. Things I don't
like about this include:

- Necessity of passing key_info<> to lookup<>. I tried to do this
   through default template args but I couldn't come up with a working
   solution.

- The separation of parameter declaration and default value definition.

- Packaging up all parameters into an MPL sequence. It's not so bad,
   though.

Would anyone find this useful? Obviously it will need some work. I'd
like to clean up the syntax some if possible.

                             -Dave

-----------------------------------

#include <libcwd/sys.h>
#include <libcwd/type_info.h>

#include <ntp.hh>
#include <io.hh>
#include <boost/mpl/map.hpp>
#include <boost/mpl/int.hpp>

#include <iostream>

MPIO_DECLARE_FILE(ntp_example_cc);

struct Key1;
struct Key2;
struct Key3;

template<typename Param1 = ntp::default_tag,
          typename Param2 = ntp::default_tag,
          typename Param3 = ntp::default_tag>
class tester {
     private:
         typedef tester<Param1, Param2, Param3> This;

         // Declare all keys and any default values
         typedef ntp::key_info<ntp::default_c<Key1, long, 1>,
                               ntp::default_c<Key2, long, 2>,
                               ntp::default_c<Key3, long, 3> > Keys;

         typedef boost::mpl::vector<Param1, Param2, Param3> Params;

         struct debug {
                 mpio::print<Params,
                             MPIO_FILE_LINE(ntp_example_cc)> print_params;
         };

         // If these are uncommented then the compiler will spew out a bunch
         // of messages.

#ifdef CT_DEBUG
         debug print_tester;

         typename ntp::key_info<ntp::default_c<Key1, long, 1>,
                                ntp::default_c<Key2, long, 2>,
                                ntp::default_c<Key3, long, 3> >::debug
print_key_info;

         typename ntp::lookup<Key1, Params, Keys>::debug print_lookup1;
         typename ntp::lookup<Key2, Params, Keys>::debug print_lookup2;
         typename ntp::lookup<Key3, Params, Keys>::debug print_lookup3;
#endif

     public:
         typedef typename ntp::lookup<Key1, Params, Keys>::type Key1Type;
         typedef typename ntp::lookup<Key2, Params, Keys>::type Key2Type;
         typedef typename ntp::lookup<Key3, Params, Keys>::type Key3Type;

         enum {
             value1 = Key1Type::value,
             value2 = Key2Type::value,
             value3 = Key3Type::value,
         };

         tester(void) {
             std::cout << "This: "
                       << libcwd::type_info_of<This>().demangled_name()
                       << std::endl;

             std::cout << "Value1: " << value1 << std::endl;
             std::cout << "Value2: " << value2 << std::endl;
             std::cout << "Value3: " << value3 << std::endl << std::endl;
         };
};

int main(void)
{
     // NTP semantics:

     // - For every param_ or param_c argument, bind the specified key

     // - For every use_default<Key>, explicitly use the default for Key

     // - For every other parameter (including use_default<>), match
     // it up with keys not otherwise specified and replace
     // use_default<> with the appropriate default value

     // - Implicitly use defaults for any remaining unmatched keys

     // Use defaults for all
     typedef tester<> empty;

     // Binds Key1
     typedef tester<boost::mpl::int_<7> > non1;

     // Binds Key1, Key2
     typedef tester<
         boost::mpl::int_<7>,
         boost::mpl::int_<8>
> non12;

     // Binds Key1, Key2, Key3
     typedef tester<
         boost::mpl::int_<7>,
         boost::mpl::int_<8>,
         boost::mpl::int_<9>
> non123;

     // Binds Key1
     typedef tester<ntp::param_c<Key1, long, 4> > key1;

     // Binds Key1, Key2
     typedef tester<
         ntp::param_c<Key1, long, 4>,
         boost::mpl::int_<8>
> key1non2def3;

     // Binds Key1, Key2
     typedef tester<
         boost::mpl::int_<8>,
         ntp::use_default<>,
         ntp::param_c<Key1, long, 4>
> key1non2def3_2;

     // Binds Key1, Key3
     typedef tester<
         ntp::param_c<Key1, long, 4>,
         ntp::use_default<Key2>,
         boost::mpl::int_<9>
> key1def2non3;

     // Binds Key1, Key2
     typedef tester<
         ntp::param_c<Key1, long, 4>,
         ntp::param_c<Key2, long, 5>
> key12;

     // Binds Key1, Key3
     typedef tester<
         ntp::param_c<Key1, long, 4>,
         ntp::param_c<Key3, long, 6>
> key13;

     // Binds Key1, Key2, Key3
     typedef tester<
         ntp::param_c<Key1, long, 4>,
         ntp::param_c<Key2, long, 5>,
         ntp::param_c<Key3, long, 6>
> key123;

     // Binds Key1, Key2, Key3
     typedef tester<
         ntp::param_c<Key1, long, 4>,
         ntp::param_c<Key3, long, 6>,
         ntp::param_c<Key2, long, 5>
> key132;

     empty print_empty;

     non1 print_non1;
     non12 print_non12;
     non123 print_non123;

     key1 print_key1;
     key1non2def3 print_key1non2def3;
     key1non2def3_2 print_key1non2def3_2;
     key1def2non3 print_key1def2non3;
     key12 print_key12;
     key13 print_key13;
     key123 print_key123;
     key132 print_key132;

     return(0);
}

--------------------------------------
Here's the output:
--------------------------------------

This: tester<ntp::default_tag, ntp::default_tag, ntp::default_tag>
Value1: 1
Value2: 2
Value3: 3

This: tester<mpl_::int_<7>, ntp::default_tag, ntp::default_tag>
Value1: 7
Value2: 2
Value3: 3

This: tester<mpl_::int_<7>, mpl_::int_<8>, ntp::default_tag>
Value1: 7
Value2: 8
Value3: 3

This: tester<mpl_::int_<7>, mpl_::int_<8>, mpl_::int_<9> >
Value1: 7
Value2: 8
Value3: 9

This: tester<ntp::param_c<Key1, long, (long)4>, ntp::default_tag,
ntp::default_tag>
Value1: 4
Value2: 2
Value3: 3

This: tester<ntp::param_c<Key1, long, (long)4>, mpl_::int_<8>,
ntp::default_tag>Value1: 4
Value2: 8
Value3: 3

This: tester<mpl_::int_<8>, ntp::use_default<mpl_::void_>,
ntp::param_c<Key1, long, (long)4> >
Value1: 4
Value2: 8
Value3: 3

This: tester<ntp::param_c<Key1, long, (long)4>, ntp::use_default<Key2>,
mpl_::int_<9> >
Value1: 4
Value2: 2
Value3: 9

This: tester<ntp::param_c<Key1, long, (long)4>, ntp::param_c<Key2, long,
(long)5>, ntp::default_tag>
Value1: 4
Value2: 5
Value3: 3

This: tester<ntp::param_c<Key1, long, (long)4>, ntp::param_c<Key3, long,
(long)6>, ntp::default_tag>
Value1: 4
Value2: 2
Value3: 6

This: tester<ntp::param_c<Key1, long, (long)4>, ntp::param_c<Key2, long,
(long)5>, ntp::param_c<Key3, long, (long)6> >
Value1: 4
Value2: 5
Value3: 6

This: tester<ntp::param_c<Key1, long, (long)4>, ntp::param_c<Key3, long,
(long)6>, ntp::param_c<Key2, long, (long)5> >
Value1: 4
Value2: 5
Value3: 6


Boost list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk