diff --git a/dune/common/CMakeLists.txt b/dune/common/CMakeLists.txt index efcfbb6d061f8a84d8636730c8d2721787aba02c..9c689c6980f6200c335d2fc6affc65f5595c39da 100644 --- a/dune/common/CMakeLists.txt +++ b/dune/common/CMakeLists.txt @@ -92,6 +92,7 @@ install(FILES sllist.hh stdstreams.hh stdthread.hh + streamoperators.hh stringutility.hh timer.hh tuples.hh diff --git a/dune/common/array.hh b/dune/common/array.hh index 6a31f5cc40e95b97fbb55e6d8de9696c4873871f..8143996d2906a6c23bf7a96d4e08788b6be8867a 100644 --- a/dune/common/array.hh +++ b/dune/common/array.hh @@ -9,9 +9,9 @@ */ #include <array> -#include <ostream> -#include "std/make_array.hh" +#include "dune/common/streamoperators.hh" +#include "dune/common/std/make_array.hh" namespace Dune { @@ -23,22 +23,6 @@ namespace Dune // pull in default implementation using std::array; - //! Output operator for array - template < class T, size_t N > - inline std::ostream& operator<< (std::ostream& s, const std::array<T,N>& e) - { - if (N == 0) - { - s << "[]"; - return s; - } - - s << "["; - for (size_t i=0; i<N-1; i++) s << e[i] << ","; - s << e[N-1] << "]"; - return s; - } - using Dune::Std::make_array; //! Create an array and fill it with copies of the provided value. diff --git a/dune/common/streamoperators.hh b/dune/common/streamoperators.hh new file mode 100644 index 0000000000000000000000000000000000000000..8af3adbbfe7b007a9a16c70f3138f9875bba0858 --- /dev/null +++ b/dune/common/streamoperators.hh @@ -0,0 +1,88 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: + +#ifndef DUNE_STREAMOPERATORS_HH +#define DUNE_STREAMOPERATORS_HH + +/** \file + \brief Implementation of stream operators for std::array and std::tuple + */ + +#include <array> +#include <ostream> +#include <tuple> + +#include <dune/common/forloop.hh> + +namespace Dune +{ + /** @addtogroup Common + + @{ + */ + + namespace + { + template<int i> + struct PrintTupleElement + { + template<typename Stream, typename Tuple> + static void apply(Stream& stream, const Tuple& t) + { + stream<<std::get<i>(t)<<","; + } + }; + + template<int i> + struct ReadTupleElement + { + template<typename Stream, typename Tuple> + static void apply(Stream& stream, Tuple& t) + { + stream>>std::get<i>(t); + } + }; + } + + //! Print a std::tuple + template<typename Stream, typename... Ts> + inline Stream& operator<<(Stream& stream, const std::tuple<Ts...>& t) + { + stream<<"["; + if(sizeof...(Ts)>0) + { + ForLoop<PrintTupleElement, 0, sizeof...(Ts)-2>::apply(stream, t); + stream<<std::get<sizeof...(Ts)-1>(t); + } + stream<<"]"; + return stream; + } + + //! Read a std::tuple + template<typename Stream, typename... Ts> + inline Stream& operator>>(Stream& stream, std::tuple<Ts...>& t) + { + ForLoop<ReadTupleElement, 0, sizeof...(Ts)-1>::apply(stream, t); + return stream; + } + + //! Print a std::array + template<typename Stream, typename T, std::size_t N> + inline Stream& operator<<(Stream& stream, const std::array<T,N>& a) + { + stream<<"["; + if(N>0) + { + for(std::size_t i=0; i<N-1; ++i) + stream<<a[i]<<","; + stream<<a[N-1]; + } + stream<<"]"; + return stream; + } + + /** @} */ + +} // end namespace Dune + +#endif diff --git a/dune/common/test/CMakeLists.txt b/dune/common/test/CMakeLists.txt index 26115f4d003324ae869c01d771e2119392f55e07..19b0bb396c3f3860b7cd0ccdd6e6c418ce581e71 100644 --- a/dune/common/test/CMakeLists.txt +++ b/dune/common/test/CMakeLists.txt @@ -157,6 +157,8 @@ dune_add_test(SOURCES stdapplytest.cc dune_add_test(SOURCES stdtypetraitstest.cc LINK_LIBRARIES dunecommon) +dune_add_test(SOURCES streamoperatorstest.cc) + dune_add_test(SOURCES streamtest.cc LINK_LIBRARIES dunecommon) @@ -198,8 +200,6 @@ dune_add_test(NAME testdebugallocator_fail5 dune_add_test(SOURCES testfloatcmp.cc) -dune_add_test(SOURCES tuplestest.cc) - dune_add_test(SOURCES tupleutilitytest.cc) #dune_add_test(SOURCES utilitytest.cc) diff --git a/dune/common/test/arraytest.cc b/dune/common/test/arraytest.cc index ce41a45e2daed216a39dfabf4c8a2491c69c404e..139764103fd386281c03339897ad89acceced29e 100644 --- a/dune/common/test/arraytest.cc +++ b/dune/common/test/arraytest.cc @@ -6,20 +6,18 @@ #endif #include <array> -#include <cstddef> #include <iostream> -#include <ostream> #include <dune/common/std/make_array.hh> #include <dune/common/classname.hh> #include <dune/common/fvector.hh> +#include <dune/common/streamoperators.hh> template<class T, std::size_t n> -void f(const std::array<T, n> &a) { - std::cout << "Got a " << Dune::className(a) << " with elements"; - for(std::size_t i = 0; i < n; ++i) - std::cout << " (" << a[i] << ")"; - std::cout << std::endl; +void f(const std::array<T, n> &a) +{ + using Dune::operator<<; + std::cout << "Got a " << Dune::className(a) << " with elements " << a << std::endl; } int main() { diff --git a/dune/common/test/integersequence.cc b/dune/common/test/integersequence.cc index ed46af0127a94880bf82c9d1d6ee80a8753ad1ea..41fadbc7105b881276436541a85b2a5ce68b5f51 100644 --- a/dune/common/test/integersequence.cc +++ b/dune/common/test/integersequence.cc @@ -5,8 +5,8 @@ #include <tuple> #include <dune/common/classname.hh> +#include <dune/common/streamoperators.hh> #include <dune/common/std/utility.hh> -#include <dune/common/tuples.hh> template< class T, std::size_t... Ints > std::tuple< typename std::tuple_element< Ints, std::array< T, sizeof...( Ints ) > >::type... > diff --git a/dune/common/test/streamoperatorstest.cc b/dune/common/test/streamoperatorstest.cc new file mode 100644 index 0000000000000000000000000000000000000000..8ee7f7b743a7e89861560fe8379d17b8f0007f63 --- /dev/null +++ b/dune/common/test/streamoperatorstest.cc @@ -0,0 +1,46 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <iostream> +#include <sstream> +#include <string> +#include <tuple> + +#include <dune/common/streamoperators.hh> + +using Dune::operator>>; +using Dune::operator<<; + +int main() +{ + typedef std::tuple<int, int, int> Tuple; + + { + const Tuple t{1, 2, 3}; + const std::string expected = "[1,2,3]"; + + std::ostringstream out; + out << t; + + if( out.str() != expected ) + return 1; + } + + { + const std::string data = "1 2 3"; + const Tuple expected{1, 2, 3}; + + std::istringstream in(data); + Tuple t; + in >> t; + + if( t != expected ) + return 1; + } + + return 0; +} diff --git a/dune/common/test/tuplestest.cc b/dune/common/test/tuplestest.cc deleted file mode 100644 index 88a863c72257ded5d28881f3751534812fee77a1..0000000000000000000000000000000000000000 --- a/dune/common/test/tuplestest.cc +++ /dev/null @@ -1,290 +0,0 @@ -// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- -// vi: set et ts=4 sw=2 sts=2: - -// make sure assert works even when not compiling for debugging -#ifdef NDEBUG -#undef NDEBUG -#endif - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <cassert> -#include <cstdlib> -#include <iostream> -#include <ostream> -#include <sstream> -#include <string> -#include <vector> -#include <tuple> - -#include <dune/common/classname.hh> -#include <dune/common/tuples.hh> - -using namespace Dune; - -template<class T> -void test(T& tuple) -{ - float f DUNE_UNUSED; - f = std::get<0>(tuple); - int i DUNE_UNUSED; - i = std::get<1>(tuple); - double d DUNE_UNUSED; - d = std::get<2>(tuple); - char c DUNE_UNUSED; - c = std::get<3>(tuple); - std::string s; - s = std::get<4>(tuple); - typename std::tuple_element<4,typename std::remove_const<T>::type>::type s2 = std::get<4>(tuple); -} - -int iteratorTupleTest() -{ - std::vector<int> v; - - v.push_back(0); - v.push_back(1); - v.push_back(2); - - typedef std::vector<int>::iterator iterator; - typedef std::vector<int>::const_iterator const_iterator; - typedef std::tuple<iterator,const_iterator, const_iterator> Tuple; - - - Tuple tuple_(v.begin(), v.begin(), v.end()); - static_assert(std::tuple_size<Tuple>::value==3, "The tuple size should be 3!");; - - int ret=0; - - if(std::get<0>(tuple_)!= v.begin()) { - std::cerr<<"Iterator tuple construction failed!"<<std::endl; - ret++; - } - assert(std::get<1>(tuple_) == v.begin()); - assert(std::get<1>(tuple_) == std::get<0>(tuple_)); - if(std::get<2>(tuple_)!= v.end()) { - std::cerr<<"Iterator tuple construction failed!"<<std::endl; - ret++; - } - - assert(std::get<2>(tuple_) == v.end()); - assert(std::get<0>(tuple_) != v.end()); - assert(std::get<1>(tuple_) != std::get<2>(tuple_)); - return ret; -} - -int lessTest() -{ - std::tuple<int,float,double> t1(1,2.0,3.0); - std::tuple<int,int,int> t2(1,2,1); - - int ret=0; - - if ((t1<t2) != false) ret++; - std::cout << "[" << t1 << "] < [" << t2 << "] = " << (t1<t2) << std::endl; - if ((t2<t1) != true) ret++; - std::cout << "[" << t2 << "] < [" << t1 << "] = " << (t2<t1) << std::endl; - - // This would result in a compiler error - // Tuple<int,int> t3(1,2); - // std::cout << "[" << t3 << "] < [" << t1 << "] = " << (t3<t1) << std::endl; - - return ret; -} - -int copyTest() -{ - std::tuple<float,int,double,char,std::string> tuple_, tuple1(3.0,1,3.3,'c',std::string("hallo")), tuple2(tuple1); - - std::cout<<tuple1<<std::endl; - std::cout<<tuple2<<std::endl; - tuple_=tuple1; - std::cout<<tuple_<<std::endl; - - if(tuple_!=tuple1) - return 1; - if(tuple2!=tuple1) - return 1; - - return 0; -} - -int referenceTest() -{ - // make sure const tuples of references have assignable members, as long as - // the member references a non-const type - { - int n = 0; - const std::tuple<int&> t(n); - std::get<0>(t) = 777; - assert(n == 777); - } - - int k=5; - int& kr(k); - kr=20; - int i=50; - double d=-3.3; - long j=-666; - std::tuple<int,double,long> t1(100, 5.0, 10); - std::tuple<int,int,int> t2(1,5,9); - std::cout << "i="<<i<<" d="<<d<<" j="<<j<<std::endl; - - std::tuple<int&,double&,long&> tr(i,d,j); - - std::get<0>(tr)=3; - assert(std::get<0>(tr)==3); - - std::cout <<"tr="<< tr<<std::endl; - - std::tuple<int> i1(5); - std::tuple<int&> ir(i); - ir=i1; - - t1=t2; - - std::cout <<"tr="<< tr<<std::endl; - std::cout <<"t1="<< t1<<std::endl; - tr=t1; - - if(tr!=t1) - return 1; - else - std::cout<<"t1="<<t1<< " tr="<<tr<<std::endl; - - - return 0; -} - -int pointerTest() -{ - int k=5, k1=6; - int i=50; - double d=-3.3, d1=7.8; - long j=-666, j1=-300; - std::tuple<int*,double*,long*> t1(&k, &d, &j); - std::tuple<int*,double*,long*> t2(&k1,&d1,&j1); - std::cout << "i="<<i<<" d="<<d<<" j="<<j<<std::endl; - - std::tuple<int*,double*,long*> tr(&i,&d,&j); - - *std::get<0>(tr)=3; - assert(*std::get<0>(tr)==3); - - std::cout <<"tr="<< tr<<std::endl; - - std::tuple<int> i1(5); - std::tuple<int*> ir(&i); - - t2=t1; - - std::cout <<"tr="<< tr<<std::endl; - std::cout <<"t1="<< t1<<std::endl; - tr=t1; - - if(tr!=t1) - return 1; - else - std::cout<<"t1="<<t1<< " tr="<<tr<<std::endl; - - - return 0; -} - -int constPointerTest() -{ - int k=5, k1=88; - int i=50; - double d=-3.3, d1=6.8; - long j=-666, j1=-500; - std::tuple<const int*, const double*, const long*> t1(&k, &d, &j); - std::tuple<int*, double*, long*> t2(&k1,&d1,&j1); - std::cout << "i="<<i<<" d="<<d<<" j="<<j<<std::endl; - - std::tuple<const int*, const double*, const long*> tr(&i,&d,&j); - - std::cout << *std::get<0>(tr)<<std::endl; - - std::cout <<"tr="<< tr<<std::endl; - - std::tuple<int> i1(5); - std::tuple<const int*> ir(&i); - - t1=t2; - - std::cout <<"tr="<< tr<<std::endl; - std::cout <<"t1="<< t1<<std::endl; - tr=t1; - - if(tr!=t1) - return 1; - else - std::cout<<"t1="<<t1<< " tr="<<tr<<std::endl; - - - return 0; -} - -int tuple_tr1_test() -{ - int ret=0; - - std::tuple<int,double> t(1,3.14); - int sz = std::tuple_size<std::tuple<int, double, char> >::value; - if(sz!=3) ++ret; - - // contruct a tuple - - t= std::make_tuple(5, 10.9); - - - // get the second element - std::tuple_element<1,std::tuple<int,double> >::type d DUNE_UNUSED; - d=std::get<1>(t); - - std::get<0>(t)=16; - - std::cout<<t<<std::endl; - - return ret; -} - -int inputTest() -{ - typedef std::tuple<int, int, int> Tuple; - const std::string data = "1, 2, 3"; - const Tuple expected{1, 2, 3}; - - std::istringstream in(data); - Tuple t; - in >> t; - - return t == expected ? 0 : 1; -} - -int outputTest() -{ - typedef std::tuple<int, int, int> Tuple; - const Tuple t{1, 2, 3}; - const std::string expected = "1, 2, 3"; - - std::ostringstream out; - out << t; - - return out.str() == expected ? 0 : 1; -} - -int main(int, char**) -{ - std::tuple<float,int,double,char,std::string> tuple_; - std::cout << "=== testing tuple: " << className(tuple_) << std::endl; - - test(tuple_); - test(static_cast<std::tuple<float,int,double,char,std::string>& >(tuple_)); - test(static_cast<const std::tuple<float,int,double,char,std::string>&>(tuple_)); - return (copyTest()+iteratorTupleTest()+referenceTest()+lessTest() - +pointerTest()+constPointerTest()+tuple_tr1_test()+inputTest()+outputTest()); - -} diff --git a/dune/common/test/tupleutilitytest.cc b/dune/common/test/tupleutilitytest.cc index e94cd9ecfc47f1c7abee3ff349059a803fa5dd7a..ffdac73c6a08ac06e1f47cfca56a1b61aee90e10 100644 --- a/dune/common/test/tupleutilitytest.cc +++ b/dune/common/test/tupleutilitytest.cc @@ -8,8 +8,8 @@ #include <cmath> #include <cstddef> #include <iostream> +#include <tuple> -#include <dune/common/tuples.hh> #include <dune/common/tupleutility.hh> ////////////////////////////////////////////////////////////////////// @@ -85,7 +85,7 @@ struct Range template<int start> struct Range<start, start> { - typedef Dune::tuple<> type; + typedef std::tuple<> type; }; // An accumulator to build up a list of divisors of an integer using reduce @@ -131,7 +131,7 @@ struct Primes typedef typename Dune::ReduceTuple< PrimeAccumulator, typename Range<1,X+1>::type, - typename Dune::tuple<> + typename std::tuple<> >::type type; }; @@ -157,7 +157,8 @@ struct Reciprocal }; }; -int main() { +int main() +{ const std::tuple<int, double> t1(1, 2.); auto t2 = Dune::genericTransformTuple(t1, Reciprocal()); static_assert(std::is_same<decltype(t2), std::tuple<double, double>>::value, diff --git a/dune/common/test/utilitytest.cc b/dune/common/test/utilitytest.cc index 1d8d3bb81afa66b7ed05f222e8dde51d6acadaaf..1ce6b4bdccd28564a26fa45fbffc192ad3c6074c 100644 --- a/dune/common/test/utilitytest.cc +++ b/dune/common/test/utilitytest.cc @@ -5,10 +5,11 @@ #include "config.h" #endif -#include <dune/common/tuples.hh> +#include <iostream> +#include <tuple> + #include <dune/common/typetraits.hh> #include <dune/common/tupleutility.hh> -#include <iostream> template<class T> struct Eval diff --git a/dune/common/tuples.hh b/dune/common/tuples.hh index 8bfd1ff86bae0f26eb99e57ed20d7dee0caea678..ea122ad5fb6dca1c6b508d0d59eb96e6e641ec85 100644 --- a/dune/common/tuples.hh +++ b/dune/common/tuples.hh @@ -1,143 +1,18 @@ -// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- -// vi: set et ts=4 sw=2 sts=2: +#warning The header dune/common/tuples.hh is deprecated. Use directly "std::tuple" and include dune/common/streamoperators.hh for stream operators. #ifndef DUNE_TUPLES_HH #define DUNE_TUPLES_HH -#include <iostream> - -#include "typetraits.hh" -#include "unused.hh" - #include <tuple> +#include <dune/common/tupleutility.hh> +#include <dune/common/streamoperators.hh> namespace Dune { - /** @addtogroup Common - * - * @{ - */ - /** - * @file - * @brief Fallback implementation of the std::tuple class - * - * This a refined implementation of the approach defined in - * in the article "Tuples and multiple return values - * in C++" of Jaakko Järvi (Turku Centre of Computer - * Science, TUCS Technical Report No 249, March 1999, - * ISBN 952-12-0401-X, ISSN 1239-1891) available from the - * <a href="http://www.tucs.fi/publications/">TUCS publications archive</a> - * @author Markus Blatt - */ - - - template<class T> - struct TupleAccessTraits - { - typedef typename std::add_const<T>::type& ConstType; - typedef T& NonConstType; - typedef const typename std::remove_const<T>::type& ParameterType; - }; - - template<class T> - struct TupleAccessTraits<T*> - { - typedef typename std::add_const<T>::type* ConstType; - typedef T* NonConstType; - typedef T* ParameterType; - }; - - template<class T> - struct TupleAccessTraits<T&> - { - typedef T& ConstType; - typedef T& NonConstType; - typedef T& ParameterType; - }; - - // pull in default implementations using std::tuple; using std::tuple_element; using std::get; using std::tuple_size; using std::tie; using std::make_tuple; - - - template<int i> - struct tuple_writer - { - template<class T> - static std::ostream& put(std::ostream& os, const T& t, const char* delim=", ") - { - return tuple_writer<i-1>::put(os,t,delim)<<delim<<Dune::get<i-1>(t); - } - - template< class T > - static std::istream &get ( std::istream &is, T &t, const char *delim = "," ) - { - tuple_writer< i-1 >::get( is, t, delim ); - for( const char *it = delim; is && (*it != 0); ++it ) - { - char c = 0; - is >> c; - if( c != *it ) - is.setstate( std::ios::failbit ); - } - return is >> Dune::get< i-1 >( t ); - } - }; - - template<> - struct tuple_writer<1> - { - template<class T> - static std::ostream& put(std::ostream& os, const T& t, const char* delim=", ") - { - DUNE_UNUSED_PARAMETER(delim); - return os<<Dune::get<0>(t); - } - - template< class T > - static std::istream &get ( std::istream &is, T &t, const char *delim = ", " ) - { - return is >> Dune::get< 0 >( t ); - } - }; - - template<> - struct tuple_writer<0> - { - template<class T> - static std::ostream& put(std::ostream& os, const T& t, const char* delim=", ") - { - return os; - } - - template< class T > - static std::istream &get ( std::istream &is, T &t, const char *delim = ", " ) - { - return is; - } - }; - - /** - * \brief Print a tuple. - */ - template<typename... Ts> - inline std::ostream& operator<<(std::ostream& os, const tuple<Ts...>& t) - { - return tuple_writer<sizeof...(Ts)>::put(os, t); - } - - /** - * \brief Read a tuple. - */ - template<typename... Ts> - inline std::istream& operator>>(std::istream& is, tuple<Ts...>& t) - { - return tuple_writer<sizeof...(Ts)>::get(is, t); - } - - /** }@ */ } #endif diff --git a/dune/common/tupleutility.hh b/dune/common/tupleutility.hh index 9a0687e2f7e51f4fcc46aa75d8ac0f8d12f28fae..b9fbe3f4910b7f0d301157e3380cc305d5b63349 100644 --- a/dune/common/tupleutility.hh +++ b/dune/common/tupleutility.hh @@ -5,14 +5,15 @@ #define DUNE_TUPLE_UTILITY_HH #include <cstddef> +#include <iostream> #include <tuple> +#include <dune/common/forloop.hh> +#include <dune/common/unused.hh> #include <dune/common/typetraits.hh> #include <dune/common/std/type_traits.hh> #include <dune/common/std/utility.hh> -#include "tuples.hh" - namespace Dune { /** @addtogroup TupleUtilities @@ -25,6 +26,30 @@ namespace Dune { * @brief Contains utility classes which can be used with std::tuple. */ + template<class T> + struct TupleAccessTraits + { + typedef typename std::add_const<T>::type& ConstType; + typedef T& NonConstType; + typedef const typename std::remove_const<T>::type& ParameterType; + }; + + template<class T> + struct TupleAccessTraits<T*> + { + typedef typename std::add_const<T>::type* ConstType; + typedef T* NonConstType; + typedef T* ParameterType; + }; + + template<class T> + struct TupleAccessTraits<T&> + { + typedef T& ConstType; + typedef T& NonConstType; + typedef T& ParameterType; + }; + /** * @brief A helper template that initializes a std::tuple consisting of pointers * to nullptr. @@ -401,7 +426,7 @@ namespace Dune { * the same as ForEachValue, just that the corresponding function object * takes one argument from the first std::tuple and one argument from the second. * - * \note You have to ensure that the two std::tuples you provide are compatible + * \note You have to ensure that the two std::tuple's you provide are compatible * in the sense that they have the same length and that the objects passed * to the function objects are related in meaningful way. The best way to * enforce it is to build the second std::tuple from the existing first std::tuple @@ -620,7 +645,7 @@ namespace Dune { template <class, class> class F, class Tuple, class Seed=std::tuple<>, - int N=tuple_size<Tuple>::value> + int N=std::tuple_size<Tuple>::value> struct ReduceTuple { typedef typename ReduceTuple<F, Tuple, Seed, N-1>::type Accumulated; @@ -681,6 +706,7 @@ namespace Dune { typedef typename ReduceTuple<JoinTuples, Tuple>::type type; }; + /** }@ */ } #endif