From 73ae395147a1a87b6b6572310ae606989ac75bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Fri, 27 Sep 2013 10:53:03 +0000 Subject: [PATCH] solve lvalue problem in container shift; refs #7 --- ax_cxx_compile_stdcxx_11.m4 | 133 ++++++++++++++++++++++++++++++++++++ configure.in | 2 + doc/examples/arguments.cxx | 81 +++++++++++----------- makefile.am | 4 +- src/makefile.am | 3 +- src/mrw/args.hxx | 104 ++++++++++------------------ src/mrw/checkcxx11.hxx | 42 ++++++++++++ src/mrw/deque.hxx | 31 ++++++++- src/mrw/iomanip.hxx | 8 +-- src/mrw/map.hxx | 38 ++++++++++- src/mrw/multimap.hxx | 39 +++++++++-- src/mrw/multiset.hxx | 33 ++++++++- src/mrw/set.hxx | 41 +++++++++-- src/mrw/vector.hxx | 32 ++++++++- 14 files changed, 452 insertions(+), 139 deletions(-) create mode 100644 ax_cxx_compile_stdcxx_11.m4 create mode 100644 src/mrw/checkcxx11.hxx diff --git a/ax_cxx_compile_stdcxx_11.m4 b/ax_cxx_compile_stdcxx_11.m4 new file mode 100644 index 0000000..af37acd --- /dev/null +++ b/ax_cxx_compile_stdcxx_11.m4 @@ -0,0 +1,133 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++11 +# standard; if necessary, add switches to CXXFLAGS to enable support. +# +# The first argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The second argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline C++11 support is required and that the macro +# should error out if no mode with that support is found. If specified +# 'optional', then configuration proceeds regardless, after defining +# HAVE_CXX11 if and only if a supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 3 + +m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; +]) + +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl + m4_if([$1], [], [], + [$1], [ext], [], + [$1], [noext], [], + [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl + m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], + [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], + [$2], [optional], [ax_cxx_compile_cxx11_required=false], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++11 features by default, + ax_cv_cxx_compile_cxx11, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ax_cv_cxx_compile_cxx11=yes], + [ax_cv_cxx_compile_cxx11=no])]) + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + m4_if([$1], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$1], [ext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) + fi + else + if test x$ac_success = xno; then + HAVE_CXX11=0 + AC_MSG_NOTICE([No compiler with C++11 support was found]) + else + HAVE_CXX11=1 + AC_DEFINE(HAVE_CXX11,1, + [define if the compiler supports basic C++11 syntax]) + fi + + AC_SUBST(HAVE_CXX11) + fi +]) diff --git a/configure.in b/configure.in index 93bf85f..eee10df 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,5 @@ # $Id$ +m4_include(ax_cxx_compile_stdcxx_11.m4) AC_ALIAS([AC_DEFINE_DIR], [AX_DEFINE_DIR]) AC_DEFUN([AX_DEFINE_DIR], [ prefix_NONE= @@ -83,6 +84,7 @@ CXXFLAGS="${CXXFLAGS:-}" # languages AC_LANG(C++) +AX_CXX_COMPILE_STDCXX_11(noext, optional) # programs AC_PROG_CXX diff --git a/doc/examples/arguments.cxx b/doc/examples/arguments.cxx index bf1d1cf..8b2155f 100644 --- a/doc/examples/arguments.cxx +++ b/doc/examples/arguments.cxx @@ -6,6 +6,9 @@ // 45678901234567890123456789012345678901234567890123456789012345678901234567890 #include +#ifdef MRW__OLD_PRE11_COMPILER +#include +#endif void test_func() { std::cout<<"test parameter was given on command line"< > params; - params.push_back(mrw::args::help()); - params.push_back(mrw::args::exit()); - options.push_back(mrw::args::declaration("h", "help", "show this help", - params)); - params.clear(); - params.push_back(mrw::args::param(r, "number")); - options.push_back(mrw::args::declaration("r", "repeat", - "number of repetitions", - params)); - params.clear(); - params.push_back(mrw::args::param(flag)); - options.push_back(mrw::args::declaration("f", "flag", "check a flag", - params)); - params.clear(); - params.push_back(mrw::args::param(txt, "text")); - options.push_back(mrw::args::declaration("t", "text", "pass a text", params)); - params.clear(); - params.push_back(mrw::args::param(x, "x")); - params.push_back(mrw::args::param(y, "y")); - options.push_back(mrw::args::declaration("c", "coord", - "add some 2D coordinates", - params)); - params.clear(); - params.push_back(mrw::args::func(test_func)); - options.push_back(mrw::args::declaration("", "test", - "call test_func, no shortcut", - params)); - mrw::args::parse(argc, argv, "This is an example for argument processing.", - options); +#ifdef MRW__OLD_PRE11_COMPILER + mrw::args::list l; + mrw::args::decl::param_list pl = mrw::args::decl::param_list(); + (mrw::args::decl::param_list())< #include #include @@ -19,43 +20,12 @@ #include #include // exit() -// check if code is compiled with a new C++11 compiler -// otherwise there is a fallback wich makes everything much more compliacted -#ifndef ARGS__OLD_PRE11_COMPILER -#if __cplusplus < 201103L -/// Code is compiled with an old non C++11 standard compliant compiler -/** There are workarounds for old non C++11 compatible - compilers. These workarounds are deprecated, but will remain until - most compilers fully support C++11. So this workaround will be - removed in future releases, when support for C++11 is more - common. Only rely on this workaround, if you really have to. - @see oldcompiler for details on usage */ -#define ARGS__OLD_PRE11_COMPILER -#warning You need a C++11 compliant compiler, on gcc use option -std=c++11 -#warning emulating C++11 - this changes the way you use the library -#warning this is deprecated and will be removed in future releases -#warning refere to the library documentation for more details -#endif -#endif - /** @page oldcompiler Workaround for old non C++11 compilers ... to be documented @note Old compilers are automatically detected and the flag - @refs ARGS__OLD_PRE11_COMPILER is set. + @refs MRW__OLD_PRE11_COMPILER is set. */ -#ifdef ARGS__OLD_PRE11_COMPILER -#include -namespace std { - // there is no std::shared_ptr in pre C++11 compilers, so we use the - // one from the boost library as a 1:1 replacement - template class shared_ptr: public boost::shared_ptr { - public: - explicit shared_ptr(T* p): boost::shared_ptr(p) {} - }; -}; -#endif - namespace mrw { /// Cool and easy evaluation of commandline arguments in C++11. /** Evaluating command line arguments is extremely easy with this library: @@ -198,46 +168,44 @@ namespace mrw { private: void(*_ref)(); }; + typedef std::shared_ptr param_ptr; template - std::shared_ptr param - (T& t, const std::string& s = std::string()) { - return std::shared_ptr(new args::parameter(t, s)); + param_ptr param(T& t, const std::string& s = std::string()) { + return param_ptr(new args::parameter(t, s)); } - struct declaration { -#ifdef ARGS__OLD_PRE11_COMPILER - declaration(std::string p1, std::string p2, std::string p3, - std::vector > p4): + struct decl { + typedef std::vector param_list; +#ifdef MRW__OLD_PRE11_COMPILER + decl(std::string p1, std::string p2, std::string p3, param_list p4): short_arg(p1), long_arg(p2), desc(p3), params(p4) { } #endif std::string short_arg; std::string long_arg; std::string desc; - std::vector > params; + param_list params; }; - typedef std::map > > - arg_map; + typedef std::map arg_map; static arg_map& args() { static arg_map a; return a; } - typedef std::vector list; + typedef std::vector list; static list& arg_list() { static list a; return a; } void match(const std::string& arg, char**& a, char** max) { -#ifdef ARGS__OLD_PRE11_COMPILER +#ifdef MRW__OLD_PRE11_COMPILER arg_map::iterator it(args().find(arg)); #else auto it(args().find(arg)); #endif if (it==args().end()) throw std::runtime_error("unknown argument: "+std::string(*a)); -#ifdef ARGS__OLD_PRE11_COMPILER - for (std::vector >::iterator - it2(it->second.begin()); it2!=it->second.end(); ++it2) +#ifdef MRW__OLD_PRE11_COMPILER + for (decl::param_list::iterator it2(it->second.begin()); + it2!=it->second.end(); ++it2) #else for (auto it2(it->second.begin()); it2!=it->second.end(); ++it2) #endif @@ -282,7 +250,7 @@ namespace mrw { returns(ret); // store return documentation for later use in help arg_list() = l; // store options and parameters for later use in help // setup the argument mapping table -#ifdef ARGS__OLD_PRE11_COMPILER +#ifdef MRW__OLD_PRE11_COMPILER for (list::iterator it(l.begin()); it!=l.end(); ++it) #else for (auto it(l.begin()); it!=l.end(); ++it) @@ -292,7 +260,7 @@ namespace mrw { if (it->long_arg.size()) args()["--"+it->long_arg] = it->params; } // parse commandline and evaluate the arguments -#ifdef ARGS__OLD_PRE11_COMPILER +#ifdef MRW__OLD_PRE11_COMPILER for (char** a(argv+1); a1&&arg[0]=='-'&&arg[1]!='-') { // short argument -#ifdef ARGS__OLD_PRE11_COMPILER +#ifdef MRW__OLD_PRE11_COMPILER for (std::string::iterator it(arg.begin()+1); it!=arg.end(); ++it) #else for (auto it(arg.begin()+1); it!=arg.end(); ++it) @@ -320,10 +288,10 @@ namespace mrw { std::cout<short_arg.size()?"-"+arg->short_arg:"")+ (arg->short_arg.size()&&arg->long_arg.size()?", ":"")+ (arg->long_arg.size()?"--"+arg->long_arg:"")); -#ifdef ARGS__OLD_PRE11_COMPILER +#ifdef MRW__OLD_PRE11_COMPILER std::string a; - for (std::vector >::iterator - p(arg->params.begin()); + for (decl::param_list::iterator p(arg->params.begin()); p!=arg->params.end(); ++p) { std::string def(**p); a+=(*p)->type()+(def.size()?"="+def:""); @@ -344,17 +311,18 @@ namespace mrw { std::string a(std::accumulate(arg->params.begin(), arg->params.end(), std::string(), [](const std::string& s, - std::shared_ptr p) + param_ptr p) -> std::string { - std::string def(**p); - return s+p->type()+(def.size()?"="+def:""); + std::string def(*p); + return + s+p->type()+(def.size()?"="+def:""); })); #endif std::cout<desc.size()>max_line-indent-option_len-param_len) - std::cout<desc; else std::cout<desc; @@ -362,7 +330,7 @@ namespace mrw { } if (returns().size()) { std::cout< func(void(*fn)()) { - return - std::shared_ptr - (new args::parameter(fn)); + param_ptr func(void(*fn)()) { + return param_ptr(new args::parameter(fn)); } - std::shared_ptr help() { + param_ptr help() { return func(args::help_no_arg); } - std::shared_ptr exit() { + param_ptr exit() { return func(args::do_exit); } } diff --git a/src/mrw/checkcxx11.hxx b/src/mrw/checkcxx11.hxx new file mode 100644 index 0000000..82e9f13 --- /dev/null +++ b/src/mrw/checkcxx11.hxx @@ -0,0 +1,42 @@ +/*! @file + + @id $Id$ +*/ +// 1 2 3 4 5 6 7 8 +// 45678901234567890123456789012345678901234567890123456789012345678901234567890 + +#ifndef __MRW__CHECKCXX11__ +#define __MRW__CHECKCXX11__ + +// check if code is compiled with a new C++11 compiler +// otherwise there is a fallback wich makes everything much more compliacted +# ifndef MRW__OLD_PRE11_COMPILER +# if __cplusplus < 201103L + /// Code is compiled with an old non C++11 standard compliant compiler + /** There are workarounds for old non C++11 compatible + compilers. These workarounds are deprecated, but will remain until + most compilers fully support C++11. So this workaround will be + removed in future releases, when support for C++11 is more + common. Only rely on this workaround, if you really have to. */ +# define MRW__OLD_PRE11_COMPILER +# warning You need a C++11 compliant compiler, on gcc use option -std=c++11 +# warning emulating C++11 - this changes the way you use the library +# warning this is deprecated and will be removed in future releases +# warning refere to the library documentation for more details +# endif +# endif + + +# ifdef MRW__OLD_PRE11_COMPILER +# include +namespace std { + // there is no std::shared_ptr in pre C++11 compilers, so we use the + // one from the boost library as a 1:1 replacement + template class shared_ptr: public boost::shared_ptr { + public: + explicit shared_ptr(T* p): boost::shared_ptr(p) {} + }; +}; +# endif + +#endif diff --git a/src/mrw/deque.hxx b/src/mrw/deque.hxx index 5122aa3..3c516f5 100644 --- a/src/mrw/deque.hxx +++ b/src/mrw/deque.hxx @@ -27,6 +27,7 @@ #define __MRW__DEQUE__HPP__ #include +#include #include #include @@ -48,11 +49,21 @@ @param o a value to be inserted into deque @c l @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::deque& operator<<(std::deque& l, const T& o) throw(std::bad_exception) { + std::deque operator<<(std::deque l, const T& o) + throw(std::bad_exception) { l.push_back(o); return l; } +#else +template + std::deque&& operator<<(std::deque&& l, const T& o) + throw(std::bad_exception) { + l.push_back(o); + return l; +} +#endif /** @brief extract the first value of a deque @@ -72,8 +83,23 @@ std::deque& operator<<(std::deque& l, const T& o) throw(std::bad_exc shortened by the shifted element @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER +template + std::deque operator>>(std::deque l, T& o) + throw(std::exception) { + typename std::deque::iterator it(l.begin()); + if (it==l.end()) + throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ + ": std::deque<>& operator>>(std::deque<>&, T&)," + " deque is empty"); + o = *it; + l.erase(it); + return l; +} +#else template -std::deque& operator>>(std::deque& l, T& o) throw(std::exception) { + std::deque&& operator>>(std::deque&& l, T& o) + throw(std::exception) { typename std::deque::iterator it(l.begin()); if (it==l.end()) throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ @@ -83,6 +109,7 @@ std::deque& operator>>(std::deque& l, T& o) throw(std::exception) { l.erase(it); return l; } +#endif //@} //@} diff --git a/src/mrw/iomanip.hxx b/src/mrw/iomanip.hxx index 4cc716d..aaf92cd 100644 --- a/src/mrw/iomanip.hxx +++ b/src/mrw/iomanip.hxx @@ -15,7 +15,7 @@ // check if code is compiled with a new C++11 compiler // otherwise there is a fallback wich makes everything much more compliacted -#ifndef ARGS__OLD_PRE11_COMPILER +#ifndef MRW__OLD_PRE11_COMPILER #if __cplusplus < 201103L /// Code is compiled with an old non C++11 standard compliant compiler /** There are workarounds for old non C++11 compatible @@ -24,7 +24,7 @@ removed in future releases, when support for C++11 is more common. Only rely on this workaround, if you really have to. @see oldcompiler for details on usage */ -#define ARGS__OLD_PRE11_COMPILER +#define MRW__OLD_PRE11_COMPILER #warning You need a C++11 compliant compiler, on gcc use option -std=c++11 #warning emulating C++11 - this changes the way you use the library #warning this is deprecated and will be removed in future releases @@ -41,7 +41,7 @@ namespace mrw { basic_split(int width=80, int indent=0, char fill=' '): _width(width), _indent(indent), _fill(fill), _os(0) { if (_width<_indent) -#ifdef ARGS__OLD_PRE11_COMPILER +#ifdef MRW__OLD_PRE11_COMPILER throw std::runtime_error(((std::stringstream&) (std::stringstream() <<"wrong use of split: width is "<<_width @@ -100,6 +100,6 @@ namespace mrw { std::stringstream _buffer; std::basic_ostream<_CharT, _Traits>* _os; }; - typedef basic_split split; + typedef basic_split ssplit; } #endif diff --git a/src/mrw/map.hxx b/src/mrw/map.hxx index 123f7d3..8852a4f 100644 --- a/src/mrw/map.hxx +++ b/src/mrw/map.hxx @@ -27,6 +27,7 @@ #define __MRW__MAP__HPP__ #include +#include #include #include @@ -50,8 +51,10 @@ @param o a value to be inserted into map @c l @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::map& operator<<(std::map& l, const std::pair& o) + std::map operator<<(std::map l, + const std::pair& o) throw(std::exception) { if (!l.insert(o).second) throw mrw::invalid_argument(std::string(__FILE__ ":")+__LINE__+ @@ -60,6 +63,19 @@ std::map& operator<<(std::map& l, const std::pair& "map element already exists"); return l; } +#else +template + std::map&& operator<<(std::map&& l, + const std::pair& o) + throw(std::exception) { + if (!l.insert(o).second) + throw mrw::invalid_argument(std::string(__FILE__ ":")+__LINE__+ + ": std::map<>&" + " operator<<(std::map<>&, const T&)," + "map element already exists"); + return l; +} +#endif /** @brief extract the first value of a map @@ -80,9 +96,10 @@ std::map& operator<<(std::map& l, const std::pair& shortened by the shifted element @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::map& operator>>(std::map& l, std::pair& o) - throw(std::exception) { + std::map operator>>(std::map l, std::pair& o) + throw(std::exception) { typename std::map::iterator it(l.begin()); if (it==l.end()) throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ @@ -92,6 +109,21 @@ std::map& operator>>(std::map& l, std::pair& o) l.erase(it); return l; } +#else +template + std::map&& operator>>(std::map&& l, + std::pair& o) + throw(std::exception) { + typename std::map::iterator it(l.begin()); + if (it==l.end()) + throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ + ": std::map<>& operator>>(std::map<>&, T&)," + " map is empty"); + o = *it; + l.erase(it); + return l; +} +#endif //@} //@} diff --git a/src/mrw/multimap.hxx b/src/mrw/multimap.hxx index 34f4580..1359bba 100644 --- a/src/mrw/multimap.hxx +++ b/src/mrw/multimap.hxx @@ -27,6 +27,7 @@ #define __MRW__MULTIMAP__HPP__ #include +#include #include #include @@ -50,12 +51,23 @@ @param o a value to be inserted into multimap @c l @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::multimap& operator<<(std::multimap& l, const std::pair& o) - throw(std::bad_exception) { + std::multimap operator<<(std::multimap l, + const std::pair& o) + throw(std::bad_exception) { l.insert(o); return l; } +#else +template && + std::multimap operator<<(std::multimap&& l, + const std::pair& o) + throw(std::bad_exception) { + l.insert(o); + return l; +} +#endif /** @brief extract the first value of a multimap @@ -76,18 +88,35 @@ std::multimap& operator<<(std::multimap& l, const std::p shortened by the shifted element @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER +template + std::multimap operator>>(std::multimap l, + std::pair& o) + throw(std::exception) { + typename std::multimap::iterator it(l.begin()); + if (it==l.end()) + throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ + ": std::multimap<>::operator>>," + " multimap is empty"); + o = *it; + l.erase(it); + return l; +} +#else template -std::multimap& operator>>(std::multimap& l, std::pair& o) - throw(std::exception) { + std::multimap&& operator>>(std::multimap&& l, + std::pair& o) + throw(std::exception) { typename std::multimap::iterator it(l.begin()); if (it==l.end()) throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ - ": std::multimap<>& operator>>(std::multimap<>&, T&)," + ": std::multimap<>::operator>>," " multimap is empty"); o = *it; l.erase(it); return l; } +#endif //@} //@} diff --git a/src/mrw/multiset.hxx b/src/mrw/multiset.hxx index 55231d3..328635a 100644 --- a/src/mrw/multiset.hxx +++ b/src/mrw/multiset.hxx @@ -27,6 +27,7 @@ #define __MRW__MULTISET__HPP__ #include +#include #include #include @@ -48,11 +49,21 @@ @param o a value to be inserted into multiset @c l @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::multiset& operator<<(std::multiset& l, const T& o) throw(std::bad_exception) { + std::multiset operator<<(std::multiset l, const T& o) + throw(std::bad_exception) { l.insert(o); return l; } +#else +template + std::multiset&& operator<<(std::multiset&& l, const T& o) + throw(std::bad_exception) { + l.insert(o); + return l; +} +#endif /** @brief extract the first value of a multiset @@ -72,17 +83,33 @@ std::multiset& operator<<(std::multiset& l, const T& o) throw( shortened by the shifted element @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::multiset& operator>>(std::multiset& l, T& o) throw(std::exception) { + std::multiset operator>>(std::multiset l, T& o) + throw(std::exception) { typename std::multiset::iterator it(l.begin()); if (it==l.end()) throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ - ": std::multiset<>& operator>>(std::multiset<>&, T&)," + ": std::multiset<> operator>>," " multiset is empty"); o = *it; l.erase(it); return l; } +#else +template + std::multiset&& operator>>(std::multiset&& l, T& o) + throw(std::exception) { + typename std::multiset::iterator it(l.begin()); + if (it==l.end()) + throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ + ": std::multiset<> operator>>," + " multiset is empty"); + o = *it; + l.erase(it); + return l; +} +#endif //@} //@} diff --git a/src/mrw/set.hxx b/src/mrw/set.hxx index 4c04ab3..d1dec66 100644 --- a/src/mrw/set.hxx +++ b/src/mrw/set.hxx @@ -27,6 +27,7 @@ #define __MRW__SET__HPP__ #include +#include #include #include @@ -49,16 +50,27 @@ @param o a value to be inserted into set @c l @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::set& operator<<(std::set& l, const T& o) - throw(std::exception) { + std::set operator<<(std::set l, const T& o) + throw(std::exception) { if (!l.insert(o).second) throw mrw::invalid_argument(std::string(__FILE__ ":")+__LINE__+ - ": std::set<>&" - " operator<<(std::set<>&, const T&)," + ": std::set<>::operator<<, " "set element already exists"); return l; } +#else +template + std::set&& operator<<(std::set&& l, const T& o) + throw(std::exception) { + if (!l.insert(o).second) + throw mrw::invalid_argument(std::string(__FILE__ ":")+__LINE__+ + ": std::set<> operator<<, " + "set element already exists"); + return l; +} +#endif /** @brief extract the first value of a set @@ -78,18 +90,33 @@ std::set& operator<<(std::set& l, const T& o) shortened by the shifted element @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::set& operator>>(std::set& l, T& o) - throw(std::exception) { + std::set operator>>(std::set l, T& o) + throw(std::exception) { typename std::set::iterator it(l.begin()); if (it==l.end()) throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ - ": std::set<>& operator>>(std::set<>&, T&)," + ": std::set<> operator>>," " set is empty"); o = *it; l.erase(it); return l; } +#else +template + std::set operator>>(std::set l, T& o) + throw(std::exception) { + typename std::set::iterator it(l.begin()); + if (it==l.end()) + throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ + ": std::set<> operator>>," + " set is empty"); + o = *it; + l.erase(it); + return l; +} +#endif //@} //@} diff --git a/src/mrw/vector.hxx b/src/mrw/vector.hxx index 2c0e6a1..804ed1b 100644 --- a/src/mrw/vector.hxx +++ b/src/mrw/vector.hxx @@ -27,6 +27,7 @@ #define __MRW__VECTOR__HPP__ #include +#include #include #include @@ -48,11 +49,21 @@ @param o a value to be inserted into vector @c l @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::vector& operator<<(std::vector& l, const T& o) throw(std::bad_exception) { + std::vector operator<<(std::vector l, const T& o) + throw(std::bad_exception) { l.push_back(o); return l; } +#else +template + std::vector&& operator<<(std::vector&& l, const T& o) + throw(std::bad_exception) { + l.push_back(o); + return l; +} +#endif /** @brief extract the first value of a vector @@ -72,8 +83,10 @@ std::vector& operator<<(std::vector& l, const T& o) throw(std::bad_e shortened by the shifted element @pre \#include */ +#ifdef MRW__OLD_PRE11_COMPILER template -std::vector& operator>>(std::vector& l, T& o) throw(std::exception) { +std::vector operator>>(std::vector l, T& o) + throw(std::exception) { typename std::vector::iterator it(l.begin()); if (it==l.end()) throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ @@ -83,7 +96,20 @@ std::vector& operator>>(std::vector& l, T& o) throw(std::exception) l.erase(it); return l; } - +#else +template +std::vector&& operator>>(std::vector&& l, T& o) + throw(std::exception) { + typename std::vector::iterator it(l.begin()); + if (it==l.end()) + throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+ + ": std::vector<>& operator>>(std::vector<>&, T&)," + " vector is empty"); + o = *it; + l.erase(it); + return l; +} +#endif //@} //@}