factor out util function to "stringify" arbitrary arguments

this function is of use also for creating a vector of strings
from a bunch of C-Strings, but it could also be used to
construct other stuff initialised by strings (e.g. RegExps)
This commit is contained in:
Fischlurch 2015-12-12 23:18:25 +01:00
parent 33f7fe116a
commit 941fe3a9b9
2 changed files with 79 additions and 32 deletions

View file

@ -46,6 +46,7 @@
#include <string>
#include <sstream>
#include <cstring>
#include <utility>
#include <typeinfo>
#include <boost/lexical_cast.hpp>
#include <boost/utility/enable_if.hpp>
@ -66,6 +67,7 @@ namespace util {
using lib::Symbol;
using util::isnil;
using std::string;
using std::move;
namespace { // we need to guard the string conversion
@ -184,6 +186,72 @@ namespace util {
: tyStr(val);
}
namespace { // helper to convert arbitrary elements toString
template<class CON>
inline void
do_stringify(CON&)
{ /* do nothing */ }
template<class CON, typename X, typename...ELMS>
inline void
do_stringify(CON& container, X const& elm, ELMS const& ...args)
{
container += util::str(elm);
do_stringify (container, args...);
}
template<class CON, typename...ELMS>
struct SeqContainer
: CON
{
void
operator+= (string&& s)
{
CON::push_back (move(s));
}
};
// most common case: use a vector container...
using std::vector;
template<typename X, typename...ELMS>
struct SeqContainer<vector<X>, ELMS...>
:vector<X>
{
SeqContainer()
{
this->reserve(sizeof...(ELMS));
}
void
operator+= (string&& s)
{
this->emplace_back (move(s));
}
};
}
/** convert a sequence of elements to string
* @param elms sequence of arbitrary elements
* @return a collection of type CON, initialised by the
* string representation of the given elements
*/
template<class CON, typename...ELMS>
inline CON
stringify(ELMS const& ...elms)
{
SeqContainer<CON,ELMS...> storage;
do_stringify (storage, elms...);
return CON {move(storage)};
}
namespace { // helper to build range iterator on demand
template<class CON, typename TOGGLE = void>
struct _RangeIter

View file

@ -68,29 +68,13 @@ namespace test{
// using lib::Literal;
using std::string;
using util::stringify;
using util::contains;
using util::isnil;
using util::_Fmt;
using lib::Symbol;
// using std::rand;
namespace {
template<class CON>
inline void
stringify(CON&)
{
/* NOP */
}
template<class CON, typename X, typename...ARGS>
inline void
stringify(CON& container, X const& elm, ARGS const& ...args)
{
container.emplace_back (util::str(elm));
stringify (container, args...);
}
}
/**
@ -390,19 +374,20 @@ namespace test{
EventMatch&
arg (ARGS const& ...args)
{
ArgSeq argSeq;
argSeq.reserve(sizeof...(ARGS));
stringify (argSeq, args...);
ArgSeq argSeq(stringify<ArgSeq> (args...));
string argList(util::join(argSeq));
solution_.andFilter (matchArguments(std::move(argSeq)));
evaluateQuery ("match-arguments("+util::join(argSeq)+")");
solution_.andFilter (matchArguments(move(argSeq)));
evaluateQuery ("match-arguments("+argList+")");
return *this;
}
template<typename... MORE>
template<typename...ARGS>
EventMatch&
argMatch (string regExp, MORE...args)
argMatch (ARGS const& ...regExps)
{
stringify<ArgSeq> (regExps...);
UNIMPLEMENTED("process regular expression match on call argument list");
}
@ -584,10 +569,7 @@ namespace test{
EventLog&
call (string target, string function, ARGS const& ...args)
{
ArgSeq argSeq;
argSeq.reserve(sizeof...(ARGS));
stringify (argSeq, args...);
return call (target, function, std::move(argSeq));
return call (target, function, stringify<ArgSeq>(args...));
}
/** Log a function call on given object ("`this`")... */
@ -609,10 +591,7 @@ namespace test{
EventLog&
note (ELMS const& ...initialiser)
{
ArgSeq args;
args.reserve(sizeof...(ELMS));
stringify (args, initialiser...);
log_->emplace_back(args);
log_->emplace_back(stringify<ArgSeq> (initialiser...));
return *this;
}