operator>> on a tied tuple with std::ignore - c++

I have stumbled upon the following problem while designing a 'generic' reader:
The following Code works perfectly fine (you need c++1z support to compile as it uses constexpr if, but with minor modifications it should also compile with c++11):
#include <vector>
#include <string>
#include <type_traits>
#include <tuple>
#include <sstream>
using namespace std;
template<int N, class tuple_type>
struct fill_tuple {
static void write(std::vector<std::string>& container, tuple_type& tuple)
{
// use operator >> to fill the N-1'th member of the tuple
std::stringstream(container[N - 1]) >> std::get<N - 1>(tuple);
if constexpr(N > 1){ // Continue if there are till fields to read
fill_tuple<N - 1, tuple_type>::write(container, tuple);
}
}
};
template<class tuple_type>
void read (std::vector<std::string>& container, tuple_type obj){
fill_tuple<std::tuple_size<tuple_type>::value, tuple_type>::write(container, obj);
}
struct some_data {
char a;
char b;
char c;
char d;
auto content() {
return std::tie(a,b,c,d);
}
};
int main()
{
std::vector<std::string> some_strings = {"a","b","c","d"};
// Read some_strings into some_data
some_data foo;
read(some_strings, foo.content());
}
For the sake of simplicity, any bound checks (such as tuple_size <= container size) are omitted.
If i wanted to parse a struct that only has members a,b and d using a container with a size of 4, my intuition was to simply rewrite std::tie(a,b,c,d) to std::tie(a,b,std::ignore,d).
This, however, fails as std::ignore (or gcc's implementation) does not seem to have a operator>> function.
I have already tried checking against std::ignore using std::is_same: std::is_same<typename std::remove_reference<typename std::tuple_element<N - 1,tuple_type>::type>::type, std::ignore>::value, but this also fails.
My question is: Is there a way to check against std::ignore, or even better, replace it entirely without relying prior modifications to the container vector?

replace it entirely without relying prior modifications to the container vector?
instead of using is_same, you may just overload against decltype(ignore); in C++17:
template<typename T>
void read_element( std::string const& s, T& t ) { std::stringstream{s} >> t; }
void read_element( std::string const&, decltype(std::ignore) const& ) { /*do nothing*/ }
std::apply( [&](auto&... args)
{
auto it = some_vector_of_strings.begin();
( read_element( *it++, args ), ... );
}, tuple );
the same idea applies to your C++11 code as well.

As state in comment, std::ignore is not a type, but an object, you have to use decltype(std::ignore) to get the type.
template <typename T>
void read_simple(const std::string& s, T& obj)
{
std::stringstream(s) >> obj;
}
void read_simple(const std::string&, const decltype(std::ignore)&) {}
template <std::size_t ... Is, typename Tuple>
void read(const std::vector<std::string>& container,
Tuple&& obj,
std::index_sequence<Is...>)
{
(read_simple(container[Is], std::get<Is>(obj)), ...);
}
template <typename Tuple>
void read(const std::vector<std::string>& container, Tuple&& obj)
{
read(container,
obj,
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
}
Demo

Related

Create a tuple from a vector of strings in c++

I have a vector of strings, each of which is the result of applying std::to_string to some basic datatype (eg char, int, double). I would like a function to undo this into a tuple of the appropriate types.
I have a simple function template to invert std::to_string:
template<typename T>
T from_string(std::string s)
{
}
template<>
int from_string<int>(std::string s)
{
return std::stoi(s);
}
template<>
double from_string<double>(std::string s)
{
return std::stod(s);
}
//... and more such specializations for the other basic types
I want a function like:
template<typename... Ts>
std::tuple<Ts> undo(const std::vector<std::string>>& vec_of_str)
{
// somehow call the appropriate specializations of from_string to the elements of vector_of_str and pack the results in a tuple. then return the tuple.
}
The function should behave like this:
int main()
{
auto ss = std::vector<std::string>>({"4", "0.5"});
auto tuple1 = undo<int, double>(ss);
std::tuple<int, double> tuple2(4, 0.5);
// tuple1 and tuple2 should be identical.
}
I think that I have to "iterate" over the parameters in Ts (perhaps the correct term is "unpack"), call the previous function, from_string for each one, and then package the results of each application of from_string into a tuple. I've seen (and used) examples that unpack a template parameter pack - they are usually recursive (but not in the usual way of a function calling itself), but I don't see how to do the rest.
An example:
#include <vector>
#include <string>
#include <tuple>
#include <cassert>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/trim.hpp>
template<class... Ts, size_t... Idxs>
std::tuple<Ts...>
parse(std::vector<std::string> const& values, std::index_sequence<Idxs...>) {
return {boost::lexical_cast<Ts>(boost::algorithm::trim_copy(values[Idxs]))...};
}
template<class... Ts>
std::tuple<Ts...> undo(std::vector<std::string> const& values) {
assert(sizeof...(Ts) == values.size());
return parse<Ts...>(values, std::make_index_sequence<sizeof...(Ts)>{});
}
int main() {
auto ss = std::vector<std::string>({"4", "0.5"});
auto tuple1 = undo<int, double>(ss);
std::tuple<int, double> tuple2(4, 0.5);
std::cout << (tuple1 == tuple2) << '\n';
assert(tuple1 == tuple2);
}
If the string values do not contain leading and/or trailing whitespace, then that call to boost::algorithm::trim_copy can be removed. It is there because boost::lexical_cast fails on whitespace.
Without boost::lexical_cast you will need to re-implement it, something like:
template<class T> T from_string(std::string const& s);
template<> int from_string<int>(std::string const& s) { return std::stoi(s); }
template<> double from_string<double>(std::string const& s) { return std::stod(s); }
// And so on.
template<class... Ts, size_t... Idxs>
std::tuple<Ts...>
parse(std::vector<std::string> const& values, std::index_sequence<Idxs...>) {
return {from_string<Ts>(values[Idxs])...};
}
For C++11 -- useful if you don't have C++14 (required by Maxim's solution), or in case you want to learn to implement recursive variadic templates:
#include <string>
#include <vector>
#include <tuple>
#include <cassert>
template <std::size_t N, typename T>
struct Undo
{
static void f(T& tuple, const std::vector<std::string>& vec_of_str)
{
Undo<N - 1, T>::f(tuple, vec_of_str);
std::get<N - 1>(tuple) = from_string<
typename std::tuple_element<N - 1, T>::type
>(vec_of_str[N - 1]);
}
};
template <typename T>
struct Undo<0, T>
{
static void f(T&, const std::vector<std::string>&)
{
}
};
template <typename... Ts>
std::tuple<Ts...> undo(const std::vector<std::string>& vec_of_str)
{
assert(vec_of_str.size() == sizeof...(Ts));
std::tuple<Ts...> ret;
Undo<sizeof...(Ts), std::tuple<Ts...>>::f(ret, vec_of_str);
return ret;
}

Get function with generic return type

I try to implement a data structure that comprises multiple name-value pairs where values may differ in their type:
template< typename T >
struct name_value_pair
{
std::string name;
T value;
};
template< typename... Ts >
class tuple_of_name_value_pairs
{
public:
/* type of value */ get_value( std::string n )
{
// return the value that the element in
// _name_value_pairs with name "n" comprises
}
private:
std::tuple<Ts...> _name_value_pairs:
};
Unfortunately, I have no idea how to implement the get function.
A workaround would be to state names as integers instead of strings and use an implementation according to std::get but this no option here: the input type of get has to be a string.
Has anyone an idea?
Firstly have in mind you cannot do what you want directly. C++ is a strongly typed language so type of function result must be known at compile time. So of course if the string you pass to the getter is known at runtime you're not able to dispatch function at compile time to let compiler deduce appropriate result type. But when you accept that you need type-erasure to erase the getter result type you could make use of e.g. boost::variant to deal with your problem. C++14 example (using boost, since c++17 variant should be available in std):
#include <boost/variant.hpp>
#include <utility>
#include <iostream>
#include <tuple>
template< typename T >
struct name_value_pair
{
using type = T;
std::string name;
T value;
};
template <std::size_t N, class = std::make_index_sequence<N>>
struct getter;
template <std::size_t N, std::size_t... Is>
struct getter<N, std::index_sequence<Is...>> {
template <class Val, class Res>
void setRes(Val &val, Res &res, std::string &s) {
if (val.name == s)
res = val.value;
}
template <class Tup>
auto operator()(Tup &tuple_vals, std::string &s) {
boost::variant<typename std::tuple_element<Is, Tup>::type::type...> result;
int helper[] = { (setRes(std::get<Is>(tuple_vals), result, s), 1)... };
(void)helper;
return result;
}
};
template <std::size_t N, class = std::make_index_sequence<N>>
struct setter;
template <std::size_t N, std::size_t... Is>
struct setter<N, std::index_sequence<Is...>> {
template <class Val, class SVal>
std::enable_if_t<!std::is_same<SVal, typename Val::type>::value> setVal(Val &, std::string &, const SVal &) { }
template <class Val>
void setVal(Val &val, std::string &s, const typename Val::type &sval) {
if (val.name == s)
val.value = sval;
}
template <class Tup, class Val>
auto operator()(Tup &tuple_vals, std::string &s, const Val &val) {
int helper[] = { (setVal(std::get<Is>(tuple_vals), s, val), 1)... };
(void)helper;
}
};
template <class T, class Res>
using typer = Res;
template< typename... Ts >
class tuple_of_name_value_pairs
{
public:
auto get_value( std::string n )
{
return getter<sizeof...(Ts)>{}(_name_value_pairs, n);
}
template <class T>
void set_value( std::string n, const T& value) {
setter<sizeof...(Ts)>{}(_name_value_pairs, n , value);
}
void set_names(typer<Ts, std::string>... names) {
_name_value_pairs = std::make_tuple(name_value_pair<Ts>{names, Ts{}}...);
}
private:
std::tuple<name_value_pair<Ts>...> _name_value_pairs;
};
int main() {
tuple_of_name_value_pairs<int, float, double> t;
t.set_names("abc", "def", "ghi");
t.set_value("abc", 1);
t.set_value("def", 4.5f);
t.set_value("ghi", 5.0);
std::cout << t.get_value("def") << std::endl;
}
[live demo]
I'm sure you'll be able to optimise the code (e.g. make use of move semantics/perfect forwarding, etc.). This is only to present you how to get your implementation started.

How to pass class template argument to boost::variant?

I have a template method that uses boost::get of boost:variant module:
typedef boost::variant<int, std::string, bool, uint8_t> Variant;
template <class T>
void write(const Variant& t) {
size_t sizeT = boost::apply_visitor(SizeOfVisitor(), t);
memcpy(&v[offset], &boost::get<T>(t), sizeT);
}
The problem is I know the underlying type of Variant only at runtime. And AFAIK I can query for it only with which() method.
Is there any way I can pass the type T, which is the underlying type of Variant to this method?
For instance, using which() I do know, what type there is, but how to pass it?
switch (m_var.which()) { // Returns an int index of types in the order of passed template classes
case 0: // This is int
case 1: // This is std::string
...
}
...
Writer.write<???>(m_var); // How to pass the type here?
EDIT: If you know any other way to achieve the desired result - actually getting the address of boost::variant inner variable, to copy from there, please share with me your ideas
Thank you
I happen to have written a very similar answer here:
C++: Extract size of boost::variant element
Again, the most important would be that it's completely bogus to use memcpy with non-POD datatypes (so you cannot use it with std::string. Ever).
The way to operate on variants with the type known only at runtime is using boost::static_visitor<>.
Here's the example with main() adapted to be close to what you wanted to achieve, apparently,
Live On Coliru
#include <boost/variant.hpp>
#include <boost/bind.hpp>
#include <boost/array.hpp> // just as a sample
#include <iostream>
namespace serialization {
namespace customization {
template<typename T, typename Out, typename R = typename boost::enable_if<boost::is_pod<T>, void>::type>
void do_serialize(T const& x, Out& out)
{
static_assert(boost::is_pod<T>(), "");
char const* rawp = reinterpret_cast<char const*>(&x);
std::copy(rawp, rawp+sizeof(T), out);
}
template<typename Out>
void do_serialize(std::string const& x, Out& out)
{
do_serialize(x.size(), out);
for(auto ch : x)
do_serialize(ch, out);
}
}
struct serialize_f : public boost::static_visitor<> {
template<typename Out, typename... T>
void operator()(boost::variant<T...> const& v, Out& out) const
{
boost::apply_visitor(boost::bind(*this, _1, boost::ref(out)), v);
}
template<typename T, typename Out>
void operator()(T const& x, Out& out) const
{
using customization::do_serialize; // ADL dispatch
do_serialize(x, out);
}
};
template <typename T, typename Out>
Out serialize(T const& v, Out out) {
const static serialize_f _vis {};
_vis(v, out);
return out;
}
}
namespace MyUserTypes {
struct A {
std::string name;
int i;
};
template<typename Out> void do_serialize(A const& v, Out& out) { // ADL will find this
serialization::serialize(v.name, out);
serialization::serialize(v.i, out);
}
}
int main() {
using namespace serialization;
std::vector<uint8_t> binary_data;
auto out_inserter = back_inserter(binary_data);
// variants and custom types
typedef boost::variant<MyUserTypes::A, boost::array<char, 42> > V;
MyUserTypes::A myA { "0123456789", 99 };
V v = boost::array<char,42>();
serialize(myA, out_inserter);
serialize(v, out_inserter);
v = myA;
serialize(v, out_inserter);
std::cout << "Bytes in binary_data vector: " << binary_data.size() << "\n";
}
switch (m_var.which()) { // Returns an int index of types in the order of passed template classes
case 0: // This is int
Writer.write<int>(m_var);
break;
case 1: // This is std::string
Writer.write<std::string>(m_var);
break;
...
}
:)

What is a good way to register functions for dynamic invocation in C++?

In my current setup, I have a
typedef std::function<void (MyClass&, std::vector<std::string>) MyFunction;
std::map<std::string, MyFunction> dispatch_map;
And I register my functions in it with a macro. However, I have a problem with this: the parameters are passed as a vector of strings, which I have to convert inside the functions. I would rather do this conversion outside the functions, at the dispatcher level. Is this possible? The function signatures are known at compile time, and never change at run time.
You can get pretty far with variadic templates and some template/virtual techniques. With the following codes, you'll be able to do something like:
std::string select_string (bool cond, std::string a, std::string b) {
return cond ? a : b;
}
int main () {
Registry reg;
reg.set ("select_it", select_string);
reg.invoke ("select_it", "1 John Wayne"));
reg.invoke ("select_it", "0 John Wayne"));
}
output:
John
Wayne
Full implementation:
These codes are exemplary. You should optimize it to provide perfect forwarding less redundancy in parameter list expansion.
Headers and a test-function
#include <functional>
#include <string>
#include <sstream>
#include <istream>
#include <iostream>
#include <tuple>
std::string select_string (bool cond, std::string a, std::string b) {
return cond ? a : b;
}
This helps us parsing a string and putting results into a tuple:
//----------------------------------------------------------------------------------
template <typename Tuple, int Curr, int Max> struct init_args_helper;
template <typename Tuple, int Max>
struct init_args_helper<Tuple, Max, Max> {
void operator() (Tuple &, std::istream &) {}
};
template <typename Tuple, int Curr, int Max>
struct init_args_helper {
void operator() (Tuple &tup, std::istream &is) {
is >> std::get<Curr>(tup);
return init_args_helper<Tuple, Curr+1, Max>() (tup, is);
}
};
template <int Max, typename Tuple>
void init_args (Tuple &tup, std::istream &ss)
{
init_args_helper<Tuple, 0, Max>() (tup, ss);
}
This unfolds a function pointer and a tuple into a function call (by function-pointer):
//----------------------------------------------------------------------------------
template <int ParamIndex, int Max, typename Ret, typename ...Args>
struct unfold_helper;
template <int Max, typename Ret, typename ...Args>
struct unfold_helper<Max, Max, Ret, Args...> {
template <typename Tuple, typename ...Params>
Ret unfold (Ret (*fun) (Args...), Tuple tup, Params ...params)
{
return fun (params...);
}
};
template <int ParamIndex, int Max, typename Ret, typename ...Args>
struct unfold_helper {
template <typename Tuple, typename ...Params>
Ret unfold (Ret (*fun) (Args...), Tuple tup, Params ...params)
{
return unfold_helper<ParamIndex+1, Max, Ret, Args...> ().
unfold(fun, tup, params..., std::get<ParamIndex>(tup));
}
};
template <typename Ret, typename ...Args>
Ret unfold (Ret (*fun) (Args...), std::tuple<Args...> tup) {
return unfold_helper<0, sizeof...(Args), Ret, Args...> ().unfold(fun, tup);
}
This function puts it together:
//----------------------------------------------------------------------------------
template <typename Ret, typename ...Args>
Ret foo (Ret (*fun) (Args...), std::string mayhem) {
// Use a stringstream for trivial parsing.
std::istringstream ss;
ss.str (mayhem);
// Use a tuple to store our parameters somewhere.
// We could later get some more performance by combining the parsing
// and the calling.
std::tuple<Args...> params;
init_args<sizeof...(Args)> (params, ss);
// This demondstrates expanding the tuple to full parameter lists.
return unfold<Ret> (fun, params);
}
Here's our test:
int main () {
std::cout << foo (select_string, "0 John Wayne") << '\n';
std::cout << foo (select_string, "1 John Wayne") << '\n';
}
Warning: Code needs more verification upon parsing and should use std::function<> instead of naked function pointer
Based on above code, it is simple to write a function-registry:
class FunMeta {
public:
virtual ~FunMeta () {}
virtual boost::any call (std::string args) const = 0;
};
template <typename Ret, typename ...Args>
class ConcreteFunMeta : public FunMeta {
public:
ConcreteFunMeta (Ret (*fun) (Args...)) : fun(fun) {}
boost::any call (std::string args) const {
// Use a stringstream for trivial parsing.
std::istringstream ss;
ss.str (args);
// Use a tuple to store our parameters somewhere.
// We could later get some more performance by combining the parsing
// and the calling.
std::tuple<Args...> params;
init_args<sizeof...(Args)> (params, ss);
// This demondstrates expanding the tuple to full parameter lists.
return unfold<Ret> (fun, params);
}
private:
Ret (*fun) (Args...);
};
class Registry {
public:
template <typename Ret, typename ...Args>
void set (std::string name, Ret (*fun) (Args...)) {
funs[name].reset (new ConcreteFunMeta<Ret, Args...> (fun));
}
boost::any invoke (std::string name, std::string args) const {
const auto it = funs.find (name);
if (it == funs.end())
throw std::runtime_error ("meh");
return it->second->call (args);
}
private:
// You could use a multimap to support function overloading.
std::map<std::string, std::shared_ptr<FunMeta>> funs;
};
One could even think of supporting function overloading with this, using a multimap and dispatching decisions based on what content is on the passed arguments.
Here's how to use it:
int main () {
Registry reg;
reg.set ("select_it", select_string);
std::cout << boost::any_cast<std::string> (reg.invoke ("select_it", "0 John Wayne")) << '\n'
<< boost::any_cast<std::string> (reg.invoke ("select_it", "1 John Wayne")) << '\n';
}
If you can use boost, then here's an example of what I think you're trying to do ( although might work with std as well, I stick with boost personally ):
typedef boost::function<void ( MyClass&, const std::vector<std::string>& ) MyFunction;
std::map<std::string, MyFunction> dispatch_map;
namespace phx = boost::phoenix;
namespace an = boost::phoenix::arg_names;
dispatch_map.insert( std::make_pair( "someKey", phx::bind( &MyClass::CallBack, an::_1, phx::bind( &boost::lexical_cast< int, std::string >, phx::at( an::_2, 0 ) ) ) ) );
dispatch_map["someKey"]( someClass, std::vector< std::string >() );
However, as this sort of nesting quickly becomes fairly unreadable, it's usually best to either create a helper ( free function, or better yet a lazy function ) that does the conversion.
If I understand you correctly, you want to register void MyClass::Foo(int) and void MyClass::Bar(float), accepting that there will be a cast from std::string to int or float as appropriate.
To do this, you need a helper class:
class Argument {
std::string s;
Argument(std::string const& s) : s(s) { }
template<typename T> operator T { return boost::lexical_cast<T>(s); }
};
This makes it possible to wrap both void MyClass::Foo(int) and void MyClass::Bar(float) in a std::function<void(MyClass, Argument))>.
Interesting problme. This is indeen not trivial in C++, I wrote a self-contained implementation in C++11. It is possible to do the same in C++03 but the code would be (even) less readable.
#include <iostream>
#include <sstream>
#include <string>
#include <functional>
#include <vector>
#include <cassert>
#include <map>
using namespace std;
// string to target type conversion. Can replace with boost::lexical_cast.
template<class T> T fromString(const string& str)
{ stringstream s(str); T r; s >> r; return r; }
// recursive construction of function call with converted arguments
template<class... Types> struct Rec;
template<> struct Rec<> { // no parameters
template<class F> static void call
(const F& f, const vector<string>&, int) { f(); }
};
template<class Type> struct Rec< Type > { // one parameter
template<class F> static void call
(const F& f, const vector<string>& arg, int index) {
f(fromString<Type>(arg[index]));
}
};
template<class FirstType, class... NextTypes>
struct Rec< FirstType, NextTypes... > { // many parameters
template<class F> static void call
(const F& f, const vector<string>& arg, int index) {
Rec<NextTypes...>::call(
bind1st(f, fromString<FirstType>(arg[index])), // convert 1st param
arg,
index + 1
);
}
};
template<class... Types> void call // std::function call with strings
(const function<void(Types...)>& f, const vector<string>& args) {
assert(args.size() == sizeof...(Types));
Rec<Types...>::call(f, args, 0);
}
template<class... Types> void call // c function call with strings
(void (*f)(Types...), const vector<string>& args) {
call(function<void(Types...)>(f), args);
}
// transformas arbitrary function to take strings parameters
template<class F> function<void(const vector<string>&)> wrap(const F& f) {
return [&] (const vector<string>& args) -> void { call(f, args); };
}
// the dynamic dispatch table and registration routines
map<string, function<void(const vector<string>&)> > table;
template<class F> void registerFunc(const string& name, const F& f) {
table.insert(make_pair(name, wrap(f)));
}
#define smartRegister(F) registerFunc(#F, F)
// some dummy functions
void f(int x, float y) { cout << "f: " << x << ", " << y << endl; }
void g(float x) { cout << "g: " << x << endl; }
// demo to show it all works;)
int main() {
smartRegister(f);
smartRegister(g);
table["f"]({"1", "2.0"});
return 0;
}
Also, for performances, it's better to use unordered_map instead of map, and maybe avoid std::function overhead if you only have regular C functions. Of course this is only meaningful if dispatch time is significant compared to functions run-times.
No, C++ provides no facility for this to occur.

In C++, is it possible to get the type of one element of a tuple when the element index is known at runtime?

typedef std::tuple< int, double > Tuple;
Tuple t;
int a = std::get<0>(t);
double b = std::get<1>(t);
for( size_t i = 0; i < std::tuple_size<Tuple>::value; i++ ) {
std::tuple_element<i,Tuple>::type v = std::get<i>(t);// will not compile because i must be known at compile time
}
I know it is possible to write code for get std::get working (see for example iterate over tuple ), is it possible to get std::tuple_element working too?
Some constraints (they can be relaxed):
no variadic templates, no Boost
C++ is a compile-time typed language. You cannot have a type that the C++ compiler cannot determine at compile-time.
You can use polymorphism of various forms to work around that. But at the end of the day, every variable must have a well-defined type. So while you can use Boost.Fusion algorithms to iterate over variables in a tuple, you cannot have a loop where each execution of the loop may use a different type than the last.
The only reason Boost.Fusion can get away with it is because it doesn't use a loop. It uses template recursion to "iterate" over each element and call your user-provided function.
If you want to do without boost, the answers to iterate over tuple already tell you everything you need to know. You have to write a compile-time for_each loop (untested).
template<class Tuple, class Func, size_t i>
void foreach(Tuple& t, Func fn) {
// i is defined at compile-time, so you can write:
std::tuple_element<i, Tuple> te = std::get<i>(t);
fn(te);
foreach<i-1>(t, fn);
}
template<class Tuple, class Func>
void foreach<0>(Tuple& t, Func fn) { // template specialization
fn(std::get<0>(t)); // no further recursion
}
and use it like that:
struct SomeFunctionObject {
void operator()( int i ) const {}
void operator()( double f ) const {}
};
foreach<std::tuple_size<Tuple>::value>(t, SomeFunctionObject());
However, if you want to iterate over members of a tuple, Boost.Fusion really is the way to go.
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
and in your code write:
boost::for_each(t, SomeFunctionObject());
This an example for boost::tuple. There is an adapter for boost::fusion to work with the std::tuple here: http://groups.google.com/group/boost-list/browse_thread/thread/77622e41af1366af/
No, this is not possible the way you describe it. Basically, you'd have to write your code for every possible runtime-value of i and then use some dispatching-logic (e.g. switch(i)) to run the correct code based on the actual runtime-value of i.
In practice, it might be possible to generate the code for the different values of i with templates, but I am not really sure how to do this, and whether it would be practical. What you are describing sounds like a flawed design.
Here is my tuple foreach/transformation function:
#include <cstddef>
#include <tuple>
#include <type_traits>
template<size_t N>
struct tuple_foreach_impl {
template<typename T, typename C>
static inline auto call(T&& t, C&& c)
-> decltype(::std::tuple_cat(
tuple_foreach_impl<N-1>::call(
::std::forward<T>(t), ::std::forward<C>(c)
),
::std::make_tuple(c(::std::get<N-1>(::std::forward<T>(t))))
))
{
return ::std::tuple_cat(
tuple_foreach_impl<N-1>::call(
::std::forward<T>(t), ::std::forward<C>(c)
),
::std::make_tuple(c(::std::get<N-1>(::std::forward<T>(t))))
);
}
};
template<>
struct tuple_foreach_impl<0> {
template<typename T, typename C>
static inline ::std::tuple<> call(T&&, C&&) { return ::std::tuple<>(); }
};
template<typename T, typename C>
auto tuple_foreach(T&& t, C&& c)
-> decltype(tuple_foreach_impl<
::std::tuple_size<typename ::std::decay<T>::type
>::value>::call(std::forward<T>(t), ::std::forward<C>(c)))
{
return tuple_foreach_impl<
::std::tuple_size<typename ::std::decay<T>::type>::value
>::call(::std::forward<T>(t), ::std::forward<C>(c));
}
The example usage uses the following utility to allow printing tuples to ostreams:
#include <cstddef>
#include <ostream>
#include <tuple>
#include <type_traits>
template<size_t N>
struct tuple_print_impl {
template<typename S, typename T>
static inline void print(S& s, T&& t) {
tuple_print_impl<N-1>::print(s, ::std::forward<T>(t));
if (N > 1) { s << ',' << ' '; }
s << ::std::get<N-1>(::std::forward<T>(t));
}
};
template<>
struct tuple_print_impl<0> {
template<typename S, typename T>
static inline void print(S&, T&&) {}
};
template<typename S, typename T>
void tuple_print(S& s, T&& t) {
s << '(';
tuple_print_impl<
::std::tuple_size<typename ::std::decay<T>::type>::value
>::print(s, ::std::forward<T>(t));
s << ')';
}
template<typename C, typename... T>
::std::basic_ostream<C>& operator<<(
::std::basic_ostream<C>& s, ::std::tuple<T...> const& t
) {
tuple_print(s, t);
return s;
}
And finally, here is the example usage:
#include <iostream>
using namespace std;
struct inc {
template<typename T>
T operator()(T const& val) { return val+1; }
};
int main() {
// will print out "(7, 4.2, z)"
cout << tuple_foreach(make_tuple(6, 3.2, 'y'), inc()) << endl;
return 0;
}
Note that the callable object is constructed so that it can hold state if needed. For example, you could use the following to find the last object in the tuple that can be dynamic casted to T:
template<typename T>
struct find_by_type {
find() : result(nullptr) {}
T* result;
template<typename U>
bool operator()(U& val) {
auto tmp = dynamic_cast<T*>(&val);
auto ret = tmp != nullptr;
if (ret) { result = tmp; }
return ret;
}
};
Note that one shortcoming of this is that it requires that the callable returns a value. However, it wouldn't be that hard to rewrite it to detect whether the return type is void for a give input type, and then skip that element of the resulting tuple. Even easier, you could just remove the return value aggregation stuff altogether and simply use the foreach call as a tuple modifier.
Edit:
I just realized that the tuple writter could trivially be written using the foreach function (I have had the tuple printing code for much longer than the foreach code).
template<typename T>
struct tuple_print {
print(T& s) : _first(true), _s(&s) {}
template<typename U>
bool operator()(U const& val) {
if (_first) { _first = false; } else { (*_s) << ',' << ' '; }
(*_s) << val;
return false;
}
private:
bool _first;
T* _s;
};
template<typename C, typename... T>
::std::basic_ostream<C> & operator<<(
::std::basic_ostream<C>& s, ::std::tuple<T...> const& t
) {
s << '(';
tuple_foreach(t, tuple_print< ::std::basic_ostream<C>>(s));
s << ')';
return s;
}