dlvhex  2.5.0
include/dlvhex2/Printhelpers.h
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005-2007 Roman Schindlauer
00003  * Copyright (C) 2006-2015 Thomas Krennwallner
00004  * Copyright (C) 2009-2016 Peter Schüller
00005  * Copyright (C) 2011-2016 Christoph Redl
00006  * Copyright (C) 2015-2016 Tobias Kaminski
00007  * Copyright (C) 2015-2016 Antonius Weinzierl
00008  *
00009  * This file is part of dlvhex.
00010  *
00011  * dlvhex is free software; you can redistribute it and/or modify it
00012  * under the terms of the GNU Lesser General Public License as
00013  * published by the Free Software Foundation; either version 2.1 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * dlvhex is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with dlvhex; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00034 #ifndef PRINTHELPERS_HPP_INCLUDED__11122011
00035 #define PRINTHELPERS_HPP_INCLUDED__11122011
00036 
00037 #include <boost/range/iterator_range.hpp>
00038 #include <boost/function.hpp>
00039 #include <boost/bind.hpp>
00040 #include <boost/optional.hpp>
00041 
00042 #include <iostream>
00043 #include <sstream>
00044 #include <set>
00045 #include <vector>
00046 
00054 template<typename T>
00055 class ostream_printable
00056 {
00061     friend std::ostream& operator<<(std::ostream& o, const T& t)
00062         { return t.print(o); }
00063     // to be defined in derived class:
00064     //std::ostream& print(std::ostream& o) const;
00065 };
00066 
00067 // if some class has a method "std::ostream& print(std::ostream&) const"
00068 // and you have an object o of this type
00069 // then you can do "std::cerr << ... << print_method(o) << ... " to print it
00070 
00071 // if some other method is used to print T foo
00072 // e.g. std::ostream& BAR::printFOO(std::ostream& o, const FOO& p) const
00073 // then you can do
00074 // std::cerr << ... << print_function(boost::bind(&BAR::printFOO, &bar, _1, foo)) << ...
00075 // e.g. std::ostream& printFOO(std::ostream& o, const FOO& p) const
00076 // then you can do
00077 // std::cerr << ... << print_function(boost::bind(&printFoo, _1, foo)) << ...
00078 
00079 // std::cerr << ... << printopt(boost::optional<T>) << ...
00080 // gives "unset" or prints T's contents
00081 
00082 // std::cerr << ... << printptr(T* or boost::shared_ptr<T>) << ...
00083 // gives "null" or prints T* as a void*
00084 
00085 // std::cerr << ... << printrange(Range r) << ... prints generic ranges enclosed in "<>"
00086 // std::cerr << ... << printvector(std::vector<T>) << ... prints generic vectors enclosed in "[]"
00087 // std::cerr << ... << printset(std::set<T>) << ... prints generic sets enclosed in "{}"
00088 
00090 struct print_container
00091 {
00093     virtual ~print_container() {}
00097     virtual std::ostream& print(std::ostream& o) const = 0;
00098 };
00099 
00104 inline std::ostream& operator<<(std::ostream& o, print_container* c)
00105 {
00106     assert(c);
00107     std::ostream& ret = c->print(o);
00108     delete c;
00109     return ret;
00110 }
00111 
00112 
00114 template<typename T>
00115 struct print_stream_container:
00116 public print_container
00117 {
00119     T t;
00122     print_stream_container(const T& t): t(t) {}
00124     virtual ~print_stream_container() {}
00125     virtual std::ostream& print(std::ostream& o) const
00126         { return o << t; }
00127 };
00128 
00130 struct print_method_container:
00131 public print_container
00132 {
00133     typedef boost::function<std::ostream& (std::ostream&)>
00134         PrintFn;
00136     PrintFn fn;
00139     print_method_container(const PrintFn& fn): fn(fn) {}
00141     virtual ~print_method_container() {}
00142     virtual std::ostream& print(std::ostream& o) const
00143         { return fn(o); }
00144 };
00145 
00149 template<typename T>
00150 inline print_container* print_method(const T& t)
00151 {
00152     return new print_method_container(
00153         boost::bind(&T::print, &t, _1));
00154 }
00155 
00156 
00164 inline print_container* print_function(
00165 const print_method_container::PrintFn& fn)
00166 {
00167     return new print_method_container(fn);
00168 }
00169 
00170 
00174 template<typename T>
00175 inline print_container* printopt(const boost::optional<T>& t)
00176 {
00177     if( !!t )
00178         return new print_stream_container<const T&>(t.get());
00179     else
00180         return new print_stream_container<const char*>("unset");
00181 }
00182 
00183 
00187 template<typename T>
00188 inline print_container* printptr(const boost::shared_ptr<T>& t)
00189 {
00190     if( !!t )
00191         return new print_stream_container<const void*>(
00192             reinterpret_cast<const void*>(t.get()));
00193     else
00194         return new print_stream_container<const char*>("null");
00195 }
00196 
00197 
00201 template<typename T>
00202 inline print_container* printptr(const boost::shared_ptr<const T>& t)
00203 {
00204     if( t != 0 )
00205         return new print_stream_container<const void*>(
00206             reinterpret_cast<const void*>(t.get()));
00207     else
00208         return new print_stream_container<const char*>("null");
00209 }
00210 
00211 
00215 template<typename T>
00216 inline print_container* printptr(const T* const t)
00217 {
00218     if( t != 0 )
00219         return new print_stream_container<const void*>(
00220             reinterpret_cast<const void* const>(t));
00221     else
00222         return new print_stream_container<const char*>("null");
00223 }
00224 
00225 
00236 template<typename Range>
00237 inline print_container* printrange(Range r,
00238 const char* open="<", const char* sep=",", const char* close=">")
00239 {
00240     std::ostringstream o;
00241     o << open;
00242     typename Range::const_iterator it = boost::begin(r);
00243     typename Range::const_iterator itend = boost::end(r);
00244     if( it != itend ) {
00245         o << *it;
00246         it++;
00247     }
00248     for(; it != itend; ++it)
00249         o << sep << *it;
00250     o << close;
00251     return new print_stream_container<std::string>(o.str());
00252 }
00253 
00254 
00265 template<typename T>
00266 inline print_container* printset(const std::set<T>& t,
00267 const char* open="{", const char* sep=",", const char* close="}")
00268 {
00269     return printrange(t, open, sep, close);
00270 }
00271 
00272 
00283 template<typename T>
00284 inline print_container* printvector(const std::vector<T>& t,
00285 const char* open="[", const char* sep=",", const char* close="]")
00286 {
00287     return printrange(t, open, sep, close);
00288 }
00289 #endif                           // PRINTHELPERS_HPP_INCLUDED__11122011
00290 
00291 // vim:expandtab:ts=4:sw=4:
00292 // mode: C++
00293 // End: