
From: "Terje Slettebø" <tslettebo@broadpark.no>
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