|
dlvhex
2.1.0
|
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