dlvhex  2.1.0
include/dlvhex2/Printhelpers.h
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005, 2006, 2007 Roman Schindlauer
00003  * Copyright (C) 2006, 2007, 2008, 2009, 2010 Thomas Krennwallner
00004  * Copyright (C) 2009, 2010 Peter Schüller
00005  * 
00006  * This file is part of dlvhex.
00007  *
00008  * dlvhex is free software; you can redistribute it and/or modify it
00009  * under the terms of the GNU Lesser General Public License as
00010  * published by the Free Software Foundation; either version 2.1 of
00011  * the License, or (at your option) any later version.
00012  *
00013  * dlvhex is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with dlvhex; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00021  * 02110-1301 USA.
00022  */
00023 
00031 #ifndef PRINTHELPERS_HPP_INCLUDED__11122011
00032 #define PRINTHELPERS_HPP_INCLUDED__11122011
00033 
00034 #include <boost/range/iterator_range.hpp>
00035 #include <boost/function.hpp>
00036 #include <boost/bind.hpp>
00037 #include <boost/optional.hpp>
00038 
00039 #include <iostream>
00040 #include <sstream>
00041 #include <set>
00042 #include <vector>
00043 
00044 // with this class, you can make your own classes ostream-printable
00045 //
00046 // usage:
00047 //   derive YourType from ostream_printable<YourType>
00048 //   implement std::ostream& YourType::print(std::ostream& o) const;
00049 //   now you can << YourType << and it will use the print() function
00050 // see http://en.wikipedia.org/wiki/Barton–Nackman_trick
00051 template<typename T>
00052 class ostream_printable
00053 {
00054   friend std::ostream& operator<<(std::ostream& o, const T& t)
00055     { return t.print(o); }
00056   // to be defined in derived class:
00057   //std::ostream& print(std::ostream& o) const;
00058 };
00059 
00060 // if some class has a method "std::ostream& print(std::ostream&) const"
00061 // and you have an object o of this type
00062 // then you can do "std::cerr << ... << print_method(o) << ... " to print it
00063 
00064 // if some other method is used to print T foo
00065 // e.g. std::ostream& BAR::printFOO(std::ostream& o, const FOO& p) const
00066 // then you can do 
00067 // std::cerr << ... << print_function(boost::bind(&BAR::printFOO, &bar, _1, foo)) << ...
00068 // e.g. std::ostream& printFOO(std::ostream& o, const FOO& p) const
00069 // then you can do 
00070 // std::cerr << ... << print_function(boost::bind(&printFoo, _1, foo)) << ...
00071 
00072 // std::cerr << ... << printopt(boost::optional<T>) << ...
00073 // gives "unset" or prints T's contents
00074 
00075 // std::cerr << ... << printptr(T* or boost::shared_ptr<T>) << ...
00076 // gives "null" or prints T* as a void*
00077 
00078 // std::cerr << ... << printrange(Range r) << ... prints generic ranges enclosed in "<>"
00079 // std::cerr << ... << printvector(std::vector<T>) << ... prints generic vectors enclosed in "[]"
00080 // std::cerr << ... << printset(std::set<T>) << ... prints generic sets enclosed in "{}"
00081 
00082 struct print_container
00083 {
00084   virtual ~print_container() {}
00085   virtual std::ostream& print(std::ostream& o) const = 0;
00086 };
00087 
00088 inline std::ostream& operator<<(std::ostream& o, print_container* c)
00089 {
00090   assert(c);
00091   std::ostream& ret = c->print(o);
00092   delete c;
00093   return ret;
00094 }
00095 
00096 template<typename T>
00097 struct print_stream_container:
00098   public print_container
00099 {
00100   T t;
00101   print_stream_container(const T& t): t(t) {}
00102   virtual ~print_stream_container() {}
00103   virtual std::ostream& print(std::ostream& o) const
00104     { return o << t; }
00105 };
00106 
00107 struct print_method_container:
00108   public print_container
00109 {
00110   typedef boost::function<std::ostream& (std::ostream&)>
00111     PrintFn;
00112   PrintFn fn;
00113   print_method_container(const PrintFn& fn): fn(fn) {}
00114   virtual ~print_method_container() {}
00115   virtual std::ostream& print(std::ostream& o) const
00116     { return fn(o); }
00117 };
00118 
00119 // this can be used if T contains a method "ostream& print(ostream&) const"
00120 template<typename T>
00121 inline print_container* print_method(const T& t)
00122 {
00123   return new print_method_container(
00124       boost::bind(&T::print, &t, _1));
00125 }
00126 
00127 // this can be used if some third party method is used to print T
00128 // e.g. std::ostream& BAR::printFOO(std::ostream& o, const FOO& p) const
00129 // is printed as
00130 // ... << print_function(boost::bind(&BAR::printFOO, &bar, _1, foo)) << ...
00131 inline print_container* print_function(
00132     const print_method_container::PrintFn& fn)
00133 {
00134   return new print_method_container(fn);
00135 }
00136 
00137 template<typename T>
00138 inline print_container* printopt(const boost::optional<T>& t)
00139 {
00140   if( !!t )
00141     return new print_stream_container<const T&>(t.get());
00142   else
00143     return new print_stream_container<const char*>("unset");
00144 }
00145 
00146 template<typename T>
00147 inline print_container* printptr(const boost::shared_ptr<T>& t)
00148 {
00149   if( !!t )
00150     return new print_stream_container<const void*>(
00151         reinterpret_cast<const void*>(t.get()));
00152   else
00153     return new print_stream_container<const char*>("null");
00154 }
00155 
00156 template<typename T>
00157 inline print_container* printptr(const boost::shared_ptr<const T>& t)
00158 {
00159   if( t != 0 )
00160     return new print_stream_container<const void*>(
00161         reinterpret_cast<const void*>(t.get()));
00162   else
00163     return new print_stream_container<const char*>("null");
00164 }
00165 
00166 template<typename T>
00167 inline print_container* printptr(const T* const t)
00168 {
00169   if( t != 0 )
00170     return new print_stream_container<const void*>(
00171         reinterpret_cast<const void* const>(t));
00172   else
00173     return new print_stream_container<const char*>("null");
00174 }
00175 
00176 template<typename Range>
00177 inline print_container* printrange(Range r,
00178         const char* open="<", const char* sep=",", const char* close=">")
00179 {
00180   std::ostringstream o;
00181   o << open;
00182   typename Range::const_iterator it = boost::begin(r);
00183   typename Range::const_iterator itend = boost::end(r);
00184   if( it != itend )
00185   {
00186     o << *it;
00187     it++;
00188   }
00189   for(; it != itend; ++it)
00190     o << sep << *it;
00191   o << close;
00192   return new print_stream_container<std::string>(o.str());
00193 }
00194 
00195 template<typename T>
00196 inline print_container* printset(const std::set<T>& t,
00197         const char* open="{", const char* sep=",", const char* close="}")
00198 {
00199   return printrange(t, open, sep, close);
00200 }
00201 
00202 template<typename T>
00203 inline print_container* printvector(const std::vector<T>& t,
00204         const char* open="[", const char* sep=",", const char* close="]")
00205 {
00206   return printrange(t, open, sep, close);
00207 }
00208 
00209 #endif // PRINTHELPERS_HPP_INCLUDED__11122011
00210