Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2004-10-10 12:59:50


>From: "Terje Slettebø" <tslettebo_at_[hidden]>
>
> This way, we get:
>
> copy<c_list>(std::back_inserter(r_list));
>
> Output of a compile-time sequence is also trivial:
>
> copy<c_list>(std::ostream_iterator<int>(std::cout,","));

Thinking about this some more, the only reason this works is that the
sequence consists of elements of the same type (integral_c derived), and
that it has an implicit conversion to the value type.

However, it would also be possible to support heterogenous sequences, but
then, the standard iterator adapters aren't sufficient, as they only work
for homogenous sequences. That's possible to make, though.

For fun, I knocked up this program, which stores values of a variety of
types in a compile-time sequence (char, int, double, rational_c and
std::string (wrapped)), prints the sequence out, copies it to a run-time
sequence (using boost::variant as element type), and prints it out, again.
It has been tested on Intel C++ 7.1 and g++ 3.2.

--- Start ---

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/variant.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/for_each.hpp>

namespace boost {

// There's a name-lookup problem finding the string stream operator, so we
provide a forwarding function

std::ostream &operator<<(std::ostream &stream,const std::string &s) {
std::operator<<(stream,s); return stream; }

// Iterator to function object conversion

template<class Iterator>
class iterator_to_functor_type
{
public:
  iterator_to_functor_type(const Iterator &i) : iterator(i) {}

  template<class Element>
  void operator()(Element e)
  {
    *iterator=e;

    ++iterator;
  }

private:
  Iterator iterator;
};

template<class Iterator>
iterator_to_functor_type<Iterator> iterator_to_functor(const Iterator &i)
{
  return iterator_to_functor_type<Iterator>(i);
}

// An ostream_iterator for heterogenous sequences

class ostream_iterator
{
public:
  ostream_iterator(std::ostream &s,const char *d) : stream(s),delimiter(d)
{}

  ostream_iterator operator*() const { return *this; }
  ostream_iterator operator++() { return *this; }

  template<class T>
  void operator=(const T &value)
  {
    stream << value << delimiter;
  }

private:
  std::ostream &stream;
  const char *delimiter;
};

namespace mpl {

// A rational_c type that works like integral_c (one may also use ref,
below)

template<class FloatType,class IntType,IntType N,IntType D>
struct rational_c
{
  operator FloatType() const { return static_cast<FloatType>(N)/D; }
};

// A compile-time reference wrapper, for types that can't be passed as
non-type template parameters

template<class T,T &value>
struct ref
{
  operator T() const { return value; }
};

// copy compile-time to run-time sequence

template<class Sequence,class Iterator>
void copy(const Iterator &i)
{
  boost::mpl::for_each<Sequence>(iterator_to_functor(i));
}

} // namespace mpl
} // namespace boost

using namespace boost;

double pi=3.14;
std::string s("Test");

int main()
{
  typedef mpl::vector<
    mpl::integral_c<char,'A'>,
    mpl::int_<123>,
    mpl::rational_c<double,int,1,2>,
    mpl::ref<double,pi>,
    mpl::ref<std::string,s>
> c_list;

  // Print compile-time sequence - "A,123,0.5,3.14,Test"

  mpl::copy<c_list>(ostream_iterator(std::cout,","));

  typedef variant<char,int,double,std::string> element_type;

  std::vector<element_type> r_list;

  // Copy from compile-time to run-time sequence

  mpl::copy<c_list>(std::back_inserter(r_list));

  // Print run-time sequence - "A,123,0.5,3.14,Test"

  std::copy(r_list.begin(),r_list.end(),ostream_iterator(std::cout,","));
}

--- End ---

Regards,

Terje


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