Can I separate creation and usage locations of compile-time strategies? - c++

#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>
using namespace std;
struct SubAlgorithm1 { void operator () (int /*i*/) { cout << "1" << endl; } };
struct SubAlgorithm2 { void operator () (int /*i*/) { cout << "2" << endl; } };
template<typename SubAlgorithm, typename Collection>
void Alrogirthm(SubAlgorithm& f, Collection& stuff) {
// In my code f is invoked ~ 1e9 times (it's a loop that is executed ~
// 1e6 times, and stuff.size() is ~1000). The application spends ~90% of
// it's time in this function, so I do not want any virtual function
// calls to slow down my number-crunching.
for (int i = 0; i < 1; ++i) for_each(stuff.begin(), stuff.end(), f);
}
int main(int , char**) {
vector<int> stuff;
stuff.push_back(1);
bool runtime_flag = true; // let's pretend it was read from config
if (runtime_flag) {
typedef SubAlgorithm1 SubAlgorithm;
SubAlgorithm sub_algorithm;
Alrogirthm(sub_algorithm, stuff);
}
else {
typedef SubAlgorithm2 SubAlgorithm;
SubAlgorithm sub_algorithm;
Alrogirthm(sub_algorithm, stuff);
}
return 0;
}
What I would really love to write instead of the if clause above:
TypeClass SubAlgorithm = runtime_flag : SubAlgorithm1 ? SubAlgorithm2;
SubAlgorithm sub_algorithm;
Algorithm(sub_algorithm, stuff);
Is there any way of doing something similar? Or some kind of completely other pattern (but not run-time polymorphism\virtual functions) to solve that issue?
P.S. In my application Algorithm has several SubAlgorithms as parameters and SubAlgorithms as well have similar structure. Moreover some SubAlgorithms have different creation interface. With run-time polymorphism I can use kind of Factory pattern and the whole thing looks nice (http://ideone.com/YAYafr), but I really cannot use virtual functions here.
P.P.S. I doubt the question phrasing reflects what I actually ask in the code, so I'd be happy to get any suggestions.

Yes. I call the technique the magic switch.
You create a std::tuple of your algorithms. You ceate a template function that will be passed one of those algorithms.
You can add other arguments via perfect variardic forwarding if you want.
template<size_t Max, typename...Ts, typename Func>
bool magic_switch( int n, Func&& f, std::tuple<Ts...> const & pick ) {
if( n==Max-1 ) {
f(std::get<Max-1>(pick));
return true;
} else {
return magic_switch<Max-1>( n, std::forward<Func>(f), pick );
}
}
In pseudo code. Specialize Max==0 to just return false, and you might have to make it a functor so you can partial specialize.
The passed in functor is annoying to write, as a downside.
Another variation is to use a meta-factory (well, a meta programming type factory? Maybe it is a meta-map. Well, whatever.)
#include <iostream>
#include <tuple>
#include <vector>
#include <utility>
#include <cstddef>
#include <functional>
#include <array>
#include <iostream>
// metaprogramming boilerplate:
template<template<typename>class Factory, typename SourceTuple>
struct tuple_map;
template<template<typename>class Factory, template<typename...>class L, typename... SourceTypes>
struct tuple_map<Factory, L<SourceTypes...>> {
typedef L< Factory<SourceTypes>... > type;
};
template<template<typename>class Factory, typename SourceTuple>
using MapTuple = typename tuple_map<Factory, SourceTuple>::type;
template<std::size_t...> struct seq {};
template<std::size_t max, std::size_t... s>
struct make_seq: make_seq<max-1, max-1, s...> {};
template<std::size_t... s>
struct make_seq<0, s...> {
typedef seq<s...> type;
};
template<std::size_t max>
using MakeSeq = typename make_seq<max>::type;
// neat little class that lets you type-erase the contents of a tuple,
// and turn it into a uniform array:
template<typename SourceTuple, typename DestType>
struct TupleToArray;
template<template<typename...>class L, typename... Ts, typename DestType>
struct TupleToArray<L<Ts...>, DestType> {
template<std::size_t... Index>
std::array< DestType, sizeof...(Ts) > operator()( L<Ts...> const& src, seq<Index...> ) const {
std::array< DestType, sizeof...(Ts) > retval{ DestType( std::get<Index>(src) )... };
return retval;
}
std::array< DestType, sizeof...(Ts) > operator()( L<Ts...> const& src ) const {
return (*this)( src, MakeSeq<sizeof...(Ts)>() );
}
};
template< typename DestType, typename SourceTuple >
auto DoTupleToArray( SourceTuple const& src )
-> decltype( TupleToArray<SourceTuple, DestType>()( src ) )
{
return TupleToArray<SourceTuple, DestType>()( src );
}
// Code from here on is actually specific to this problem:
struct SubAlgo { int operator()(int x) const { return x; } };
struct SubAlgo2 { int operator()(int x) const { return x+1; } };
template<typename Sub>
struct FullAlgo {
void operator()( std::vector<int>& v ) const {
for( auto& x:v )
x = Sub()( x );
}
};
// a bit messy, but I think I could clean it up:
typedef std::tuple< SubAlgo, SubAlgo2 > subAlgos;
MapTuple< FullAlgo, subAlgos > fullAlgos;
typedef std::function< void(std::vector<int>&) > funcType;
std::array< funcType, 2 > fullAlgoArray =
DoTupleToArray< funcType >( fullAlgos );
int main() {
std::vector<int> test{1,2,3};
fullAlgoArray[0]( test );
for (auto&& x: test)
std::cout << x;
std::cout << "\n";
fullAlgoArray[1]( test );
for (auto&& x: test)
std::cout << x;
std::cout << "\n";
}
which is lots of boilerplate, but what I've just done is allowed you to take your stateless sub algorithm and plug it into your full algorithm one element at a time, then type-erase the resulting full algorithm and store it in a std::function array.
There is a virtual call overhead, but it occurs at the top level.

You should use an interface, with both SubAlgorithm1 and SubAlgorithm2 (you'll need better names than that) implementing the interface. The create an object of either class depending on runtime_flag.

Related

An unordered_map that returns pairs of different types c++

I am trying to implement an std::unordered_map that returns pairs of either double, int or std::string. The keys for the map are std::strings. Below is what I have tried so far:
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <utility>
#include <vector>
// A base class for boundary class
class Boundbase {
public:
Boundbase(){};
virtual ~Boundbase(){};
};
// A different map of boundaries for each different data type
template <class dType>
class Boundary : public Boundbase {
std::pair<dType, dType> bpair;
public:
//Constructor
Boundary(const std::string &lbound,
const std::string &ubound) {
setbound(lbound, ubound);
};
//A method to set boundary pair
void setbound(const std::string &lbound,
const std::string &ubound);
// A method to get boundary pair
std::pair<dType, dType> getbound() {return bpair;}
};
// Class to hold the different boundaries
class Boundaries {
std::unordered_map<std::string, Boundbase*> bounds;
public:
//Constructor
Boundaries() {};
// A method to set boundary map
void setboundmap(std::unordered_map<std::string,
std::vector<std::string>> xtb);
// A template to get boundaries.
std::unordered_map<std::string, Boundbase*> getbounds()
{return bounds;}
};
// A method to set covariate boundary
template <class dType> void
Boundary<dType>::setbound(const std::string &lbound,
const std::string &ubound) {
dType val;
std::istringstream isa(lbound);
while(isa >> val) {
bpair.first = val;
}
std::istringstream isb(ubound);
while(isb >> val) {
bpair.second = val;
}
}
// A method to set boundary map
void Boundaries::setboundmap(std::unordered_map<std::string,
std::vector<std::string>> xtb) {
for(auto s : xtb) {
char type = s.second[1][0];
switch(type) {
case 'd': {
std::pair<std::string, Boundbase*> opair;
opair.first = s.first;
opair.second = new Boundary<double>(
s.second[2], s.second[3]);
bounds.insert(opair);
}
break;
case 'i': {
std::pair<std::string, Boundbase*> opair;
opair.first = s.first;
opair.second = new Boundary<int>(
s.second[2], s.second[3]);
bounds.insert(opair);
break;
}
case 'c': {
std::pair<std::string, Boundbase*> opair;
opair.first = s.first;
opair.second = new Boundary<std::string>(
s.second[2], s.second[2]);
bounds.insert(opair);
break;
}
}
}
}
This compiles ok using g++. When I try to run it though ( as follows):
int main() {
Data D;
Boundaries B;
std::ifstream iss("tphinit.txt");
D.read_lines(iss);
auto dbounds = D.get_xtypebound();
B.setboundmap(dbounds);
auto tbounds = B.getbounds();
auto sbound = tbounds["X1"];
std::cout << sbound->bpair.first << ","
<< sbound->bpair.second << std::endl;
}
I get 'class Boundbase' has no member named 'bpair' which is true because I am pointing to the base class and not the derived class. As far as I can tell, trying to get the derived member bpair requires that I use the visitor pattern. Now, it is clear that I am noob so when I had a look at different ways of doing this on SO I was a little in over my head (no reflection on the authors, just on my inexperience).
So my main question is: Is this the best and simplest way to go about this? I would like to avoid boost::variant if at all possible (mainly for the sake of purity: this cannot be that difficult). A sub-question is whether I have to use the visitor pattern or is there a better/simpler way to get the member pbair?
I will have to perform this lookup many times so I am hoping to make it as fast as possible but using the stl for the sake of simplicity.
Make your values std variants over the 3 types.
Failing that, boost variant.
Std and boost variant really are what you want. You'll end up implementing some subset of its implementation.
Failing that, find a tutorial on how to implement ones of them, or use std any. Failing that, dynamic casts around an otherwise useless wrapper type with a virtual dtor stored in a unique ptr, or do manual RTTI with try get methods.
This just gets increasingly ugly and/or inefficient however.
Boost variant, and std variant from it, was implemented for a reason, and that reason was solving the exact problem you are describing in an efficient manner.
#include <tuple>
#include <utility>
#include <string>
template<class...Ts>
struct destroy_helper {
std::tuple<Ts*...> data;
destroy_helper( std::tuple<Ts*...> d ):data(d){}
template<class T>
static void destroy(T* t){ t->~T(); }
template<std::size_t I>
void operator()(std::integral_constant<std::size_t, I>)const {
destroy( std::get<I>( data ) );
}
};
struct construct_helper {
template<class T, class...Args>
void operator()(T* target, Args&&...args)const {
::new( (void*)target ) T(std::forward<Args>(args)...);
}
};
template<std::size_t...Is>
struct indexes {};
template<std::size_t N, std::size_t...Is>
struct make_indexes:make_indexes<N-1, N-1, Is...> {};
template<std::size_t...Is>
struct make_indexes<0, Is...>{
using type=indexes<Is...>;
};
template<std::size_t N>
using make_indexes_t = typename make_indexes<N>::type;
template<class F>
void magic_switch( std::size_t i, indexes<>, F&& f ) {}
template<std::size_t I0, std::size_t...Is, class F>
void magic_switch( std::size_t i, indexes<I0,Is...>, F&& f )
{
if (i==I0) {
f( std::integral_constant<std::size_t, I0>{} );
return;
}
magic_switch( i, indexes<Is...>{}, std::forward<F>(f) );
}
template<class T0>
constexpr T0 max_of( T0 t0 ) {
return t0;
}
template<class T0, class T1, class...Ts>
constexpr T0 max_of( T0 t0, T1 t1, Ts... ts ) {
return (t1 > t0)?max_of(t1, ts...):max_of(t0, ts...);
}
template<class...Ts>
struct Variant{
using Data=typename std::aligned_storage< max_of(sizeof(Ts)...), max_of(alignof(Ts)...)>::type;
std::size_t m_index=-1;
Data m_data;
template<std::size_t I>
using alternative_t=typename std::tuple_element<I, std::tuple<Ts...>>::type;
using pointers=std::tuple<Ts*...>;
using cpointers=std::tuple<Ts const*...>;
template<class T> T& get(){ return *reinterpret_cast<T*>(&m_data); }
template<class T> T const& get() const { return *reinterpret_cast<T*>(&m_data); }
template<std::size_t I>
alternative_t<I>& get(){ return std::get<I>(get_pointers()); }
template<std::size_t I>
alternative_t<I> const& get()const{ return std::get<I>(get_pointers()); }
pointers get_pointers(){
return pointers( (Ts*)&m_data... );
}
cpointers get_pointers()const{
return cpointers( (Ts const*)&m_data... );
}
std::size_t alternative()const{return m_index;}
void destroy() {
if (m_index == -1)
return;
magic_switch(m_index, make_indexes_t<sizeof...(Ts)>{}, destroy_helper<Ts...>(get_pointers()));
}
template<std::size_t I, class...Args>
void emplace(Args&&...args) {
destroy();
construct_helper{}( std::get<I>(get_pointers()), std::forward<Args>(args)... );
m_index = I;
}
Variant()=default;
Variant(Variant const&)=delete;//todo
Variant&operator=(Variant const&)=delete;//todo
Variant(Variant &&)=delete;//todo
Variant&operator=(Variant &&)=delete;//todo
~Variant(){destroy();}
};
int main() {
Variant<int, double, std::string> bob;
bob.emplace<0>( 7 );
bob.emplace<1>( 3.14 );
bob.emplace<2>( "hello world" );
}
here is a really simple variant interface.
The hard part is turning a runtime index into which of the compile time indexes you want to use. I call that the magic switch problem.
You might also want to implement apply visitor.
...
Or...
template<class T>
struct Derived;
struct Base {
virtual ~Base() {}
template<class T>
friend T* get(Base* base) {
Derived<T>* self = dynamic_cast<T*>(base);
return self?&self.t:nullptr;
}
template<class T>
friend T const* get(Base const* base) {
Derived<T> const* self = dynamic_cast<T const*>(base);
return self?&self.t:nullptr;
}
};
template<class T>
struct Derived:Base {
Derived(T in):t(std::move(in)){}
T t;
};
std::unordered_map<std::string, std::unique_ptr<Base>> map;
map["hello"] = std::unique_ptr<Base>( new Derived<int>(-1) );
map["world"] = std::unique_ptr<Base>( new Derived<double>(3.14) );
int* phello = get<int>(map["hello"]);
if (phello) std::cout << *hello << "\n";
double* pworld = get<double>(map["world"]);
if (pworld) std::cout << *world << "\n";
which is a seriously bargain-basement std::any.

Unpack Data for Variadic Template Function Calls stored as Array (Goal:RPC)

The idea is to create the following functionality (Looks easy)
void test(int , float , char* ){ /*gets called*/ }
void main()
{
RegisterRPC( test , int , float , char* )
}
Pseudo-code to register the function:
std::map<std::string , std::function<void()> > functionarray;
template<typename F, typename... Args>
void RegisterRPC( F , Args )
{
// somehow add to functionarray
}
Then, when data comes from Network, the data needs to be decomposed to call test with the proper args.
ProcessData(data)
{
data.begin();
functionarray[data.get<char*>()] (
data.get<int>() ,
data.get<float>() ,
data.get<char*>() ); // the RegisterRPC parameters
}
I already found that Variadic Templates can store args
expanded parameter list for variadic template
And it can decopose args into classes
How can I iterate over a packed variadic template argument list?
So I believe its possible - just I dont get how..
Hope somebody can help.
Edit : In case somebody is interested in the complete solution :
#include <tuple>
#include <iostream>
#include <strstream>
#include <istream>
#include <sstream>
#include <string>
// ------------- UTILITY---------------
template<int...> struct index_tuple{};
template<int I, typename IndexTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
// ----------UNPACK TUPLE AND APPLY TO FUNCTION ---------
using namespace std;
template<class Ret, class... Args, int... Indexes >
Ret apply_helper(Ret(*pf)(Args...), index_tuple< Indexes... >, tuple<Args...>&& tup)
{
return pf(forward<Args>(get<Indexes>(tup))...);
}
template<class Ret, class ... Args>
Ret apply(Ret(*pf)(Args...), const tuple<Args...>& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(), tuple<Args...>(tup));
}
template<class Ret, class ... Args>
Ret apply(Ret(*pf)(Args...), tuple<Args...>&& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(), forward<tuple<Args...>>(tup));
}
// --- make tuple ---
template <typename T> T read(std::istream& is)
{
T t; is >> t; cout << t << endl; return t;
}
template <typename... Args>
std::tuple<Args...> parse(std::istream& is)
{
return std::make_tuple(read<Args>(is)...);
}
template <typename... Args>
std::tuple<Args...> parse(const std::string& str)
{
std::istringstream ips(str);
return parse<Args...>(ips);
};
// ---- RPC stuff
class DataSource
{
std::string data;
public:
DataSource(std::string s) { data = s; };
template<class...Ts> std::tuple<Ts...> get() { return parse<Ts...>(data); };
};
std::map<std::string, std::function<void(DataSource*)> > functionarray;
template<typename... Args, class F>
void RegisterRPC(std::string name, F f) {
functionarray[name] = [f](DataSource* data){apply(f, data->get<Args...>()); };
}
// --------------------- TEST ------------------
void one(int i, double d, string s)
{
std::cout << "function one(" << i << ", " << d << ", " << s << ");\n";
}
int main()
{
RegisterRPC<int, double, string>("test1", one);
DataSource* data=new DataSource("5 2 huhu");
functionarray["test1"](data);
system("pause");
return 0;
}
// --------------------- TEST ------------------
First, write a "call with tuple". This takes a callable object f and a tuple t, and calls f( std::get<0>(t), std::get<1>(t), ... ).
here is one of many such implementations on stack overflow. You can write a better one in C++14, or wait for it to arrive in C++1z.
Second, write data.get<std::tuple<A,B,C,...>>() that returns a tuple of type A,B,C,.... This is easy:
template<class...Ts>
std::tuple<Ts...> DataSource::get() {
return std::tuple<Ts...>{get<Ts>()...}; // some compilers get order here wrong, test!
}
now our function array looks like this:
std::map<std::string , std::function<void(DataSource*)> > functionarray;
template<class...Args, class F>
std::function<void(DataSource*)> from_source( F f ) {
// `[f = std::move(f)]` is C++14. In C++11, just do `[f]` instead
return [f = std::move(f)](DataSource* data){
call_from_tuple( f, data->get<std::tuple<Args...>>() );
};
}
template<typename... Args, class F>
void RegisterRPC( F f ) {
functionarray.push_back( from_source<Args...>( std::move(f) ) );
}
and end use is:
void test(int , float , char* ){ /*gets called*/ }
void main()
{
RegisterRPC<int,float,char*>( test )
}
I recomment against using char*. I'd use std::string, or std::vector<char> or even std::unique_ptr<char[]>, so lifetime is extremely clear.
The trick is that we erase at the point where we know the type information, which is where we wrap the function. There, we give it instructions on how to get the types from the data source and call itself, leaving behind a function of type "data source -> nothing".
We take "Ts... -> nothing" (your F) and "(DataSource -> Ts)..." (the stream of data over the network) and compose it into "DataSource -> nothing" (the std::function you store).

Compile time check that string to enum map is complete

This question may very well be the n-th iteration of "How to map strings to enums".
My requirements go a little bit further and I want to throw a certain exception when a key is not found in the range of valid inputs. So I have this implementation of this EnumMap (needs boost for const std::map definition):
#include <map>
#include <string>
#include <sstream>
#include <stdexcept>
#include <boost/assign.hpp>
typedef enum colors {
RED,
GREEN,
} colors;
// boost::assign::map_list_of
const std::map<std::string,int> colorsMap = boost::assign::map_list_of
("red", RED)
("green", GREEN);
//-----------------------------------------------------------------------------
// wrapper for a map std::string --> enum
class EnumMap {
private:
std::map<std::string,int> m_map;
// print the map to a string
std::string toString() const {
std::string ostr;
for(auto x : m_map) {
ostr += x.first + ", ";
}
return ostr;
}
public:
// constructor
EnumMap(const std::map<std::string,int> &m) : m_map(m) { }
// access
int at(const std::string &str_type) {
try{
return m_map.at(str_type);
}
catch(std::out_of_range) {
throw(str_type + " is not a valid input, try : " + toString());
}
catch(...) {
throw("Unknown exception");
}
}
};
//-----------------------------------------------------------------------------
int main()
{
EnumMap aColorMap(colorsMap);
try {
aColorMap.at("red"); // ok
aColorMap.at("yellow"); // exception : "yellow is not a valid input ..."
}
catch(std::string &ex) {
std::cout << ex << std::endl;
}
return 0;
}
This works well and does what I need. Now, I want to make it possible to know at compile time that all the elements in a certain enum are passed to the EnumMap constructor, and also that all the elements in the enum are matched with the corresponding string.
I tried with std::initializer_list and static_assert, but it seems that VC2010 does not still support std::initializer_list (see here).
Does anyone have an idea on how it would be possible to implement this? Perhaps with templates, or implementing my own Enum class?
typedef enum colors {
MIN_COLOR,
RED = MIN_COLOR,
GREEN,
MAX_COLOR
} colors;
template< colors C >
struct MapEntry {
std::string s;
MapEntry(std::string s_):s(s_) {}
};
void do_in_order() {}
template<typename F0, typename... Fs>
void do_in_order(F0&& f0, Fs&&... fs) {
std::forward<F0>(f0)();
do_in_order( std::forward<Fs>(fs)... );
}
struct MapInit {
std::map< std::string, color > retval;
operator std::map< std::string, color >() {
return std::move(retval);
}
template<colors C>
void AddToMap( MapEntry<C>&& ent ) {
retval.insert( std::make_pair( std::move(end.s), C ) );
}
template< typename... Entries >
MapInit( Entries&& entries ) {
do_in_order([&](){ AddToMap(entries); }...);
}
};
template<typename... Entries>
MapInit mapInit( Entries&&... entries ) {
return MapInit( std::forward<Entries>(entries)... );
}
const std::map<std::string, colors> = mapInit( MapEntry<RED>("red"), MapEntry<GREEN>("green") );
which gives you a C++11 way to construct a std::map from compile time color and run-time string data.
Throw in a "list of MapEntry<colors> to list of colors" metafunction next.
template<colors... Cs>
struct color_list {};
template<typename... Ts>
struct type_list {};
template<typename MapEnt>
struct extract_color;
template<colors C>
struct extract_color<MapEntry<C>> {
enum {value=C};
};
template<typename Entries>
struct extract_colors;
template<typename... MapEntries>
struct extract_colors<type_list<MapEntries...>> {
typedef color_list< ( (colors)extract_colors<MapEntries>::value)... > type;
};
Sort that list. Detect duplicates -- if there are, you screwed up.
Compile-time sorting is harder than the rest of this, and a 100+ lines of code. I'll leave it out if you don't mind too much! Here is a compile time merge sort I wrote in the past to answer a stack overflow question that would work with relatively simple adaptation (it sorts types with values, in this case we are sorting a list of compile-time values directly).
// takes a sorted list of type L<T...>, returns true if there are adjacent equal
// elements:
template<typename clist, typename=void>
struct any_duplicates:std::false_type {};
template<typename T, template<T...>class L, T t0, T t1, T... ts>
struct any_duplicates< L<t0, t1, ts...>, typename std::enable_if<t0==t1>::type>:
std::true_type {};
template<typename T, template<T...>class L, T t0, T t1, T... ts>
struct any_duplicates< L<t0, t1, ts...>, typename std::enable_if<t0!=t1>::type>:
any_duplicates< L<t1, ts...> > {};
Detect elements outside of the valid range of colors (ie, <MIN_COLOR or >=MAX_COLOR). If so, you screwed up.
template<typename List>
struct min_max;
template<typename T, template<T...>class L, T t0>
struct min_max {
enum {
min = t0,
max = t1,
};
};
template<typename T, template<T...>class L, T t0, T t1, T... ts>
struct min_max {
typedef min_max<L<t1, ts...>> rest_of_list;
enum {
rest_min = rest_of_list::min,
rest_max = rest_of_list::max,
min = (rest_min < t0):rest_min:t0,
max = (rest_max > t0):rest_max:t0,
};
};
template< typename T, T min, T max, typename List >
struct bounded: std::integral_constant< bool,
(min_max<List>::min >= min) && (min_max<List>::max < max)
> {};
Count how many elements there are -- there should be MAX_COLOR elements. If not, you screwed up.
template<typename List>
struct element_count;
template<typename T, template<T...>L, T... ts>
struct element_count<L<ts...>>:std::integral_constant< std::size_t, sizeof...(ts) > {};
If none of these occurred, by pigeonhole you must have initialized each of them.
The only thing missing is that you could have gone off and used the same string for two values. As compile time strings are a pain, just check this at run time (that the number of entries in the map equals the number of colors after you initialize it).
Doing this in C++03 will be harder. You lack variardic templates, so you end up having to fake them. Which is a pain. mpl might be able to help you there.
Variardic templates are available in the Nov 2012 MSVC CTP compiler update.
Here is a toy example without duplicate checking and without bounds checking (it just checks that the number of map entries matches);
#include <cstddef>
#include <utility>
#include <string>
#include <map>
enum TestEnum {
BeginVal = 0,
One = BeginVal,
Two,
Three,
EndVal
};
template<TestEnum e>
struct MapEntry {
enum { val = e };
std::string s;
MapEntry( std::string s_ ):s(s_) {}
};
void do_in_order() {}
template<typename F0, typename... Fs>
void do_in_order(F0&& f0, Fs&&... fs) {
std::forward<F0>(f0)();
do_in_order( std::forward<Fs>(fs)... );
}
template<typename... MapEntries>
struct count_entries:std::integral_constant< std::size_t, sizeof...(MapEntries) > {};
// should also detect duplicates and check the range of the values:
template<typename... MapEntries>
struct caught_them_all:
std::integral_constant<
bool,
count_entries<MapEntries...>::value == (TestEnum::EndVal-TestEnum::BeginVal)
>
{};
struct BuildMap {
typedef std::map<std::string, TestEnum> result_map;
mutable result_map val;
operator result_map() const {
return std::move(val);
}
template<typename... MapEntries>
BuildMap( MapEntries&&... entries ) {
static_assert( caught_them_all<MapEntries...>::value, "Missing enum value" );
bool _[] = { ( (val[ entries.s ] = TestEnum(MapEntries::val)), false )... };
}
};
std::map< std::string, TestEnum > bob = BuildMap(
MapEntry<One>("One")
,MapEntry<Two>("Two")
#if 0
,MapEntry<Three>("Three")
#endif
);
int main() {}
Replace the #if 0 with #if 1 to watch it compile. Live link if you want to play.
Does anyone have an idea on how it would be possible to implement this? Perhaps with templates, or implementing my own Enum class?
It is not possible to do. Not with std::map, and not with template meta-programming.
I want to post the solution I arrived finally. I don't want to mark it as a definitive answer because I would like to figure out if we can define the vectors of strings at compile time.
//
// Cumstom Enum Header File
//
#include <vector>
#include <string>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/range/algorithm/find.hpp>
std::vector<std::string> split_to_vector(std::string s)
{
// splits a comma separated string to a vector of strings
std::vector<std::string> v;
boost::split(v, s, boost::is_any_of(", "), boost::token_compress_on);
return v;
}
#define ENUM_TO_STRING(X,...) \
struct X { \
enum Enum {__VA_ARGS__}; \
static \
std::string to_string(X::Enum k) { \
std::vector<std::string> keys = split_to_vector(#__VA_ARGS__); \
return keys[static_cast<int>(k)]; \
} \
static \
X::Enum which_one(const std::string s) { \
std::vector<std::string> keys = split_to_vector(#__VA_ARGS__); \
auto it = boost::find(keys, s); \
if(it == keys.end()) { \
throw("not a valid key"); \
} \
return static_cast<X::Enum>(it - keys.begin()); \
} \
}
//
// Usage
//
#include <iostream>
ENUM_TO_STRING(Color, Red, Green, Blue);
int main()
{
std::string red_s = Color::to_string(Color::Red);
std::cout << red_s << std::endl;
Color::Enum red_e = Color::which_one("Red");
std::cout << red_e << std::endl;
// won't compile
// std::string yellow_s = Colors::to_string(Colors::Yellow);
// run-time error
// Color::Enum yellow_e = Colors::which_one("Yellow");
}
Run it on Coliru:
http://coliru.stacked-crooked.com/a/e81e1af0145df99a

Type sensitive tuple visitor

Suppose I have a std::tuple made up of types like
struct A {
static void tip();
};
struct B {
static void tip();
};
struct Z {
};
std::tuple<const A&,const B&,const Z&> tpl;
Yes, I need separate A, B. (The implementation of ::tip() differs for each type.) What I try to implement is a type-sensitive "visitor" that iterates through the tuple starting from the beginning to the end. Upon visiting a particular element of type T a function should be called depending on whether T has the ::tip() method or not. In the simple example of above only A and B have ::tip() implemented and Z not. So, the iterator should call twice the function for types with the ::tip() method and once the other function.
Here is what I came up with:
template< int N , bool end >
struct TupleIter
{
template< typename T , typename... Ts >
typename std::enable_if< std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
template< typename T , typename... Ts >
typename std::enable_if< ! std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "no tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
};
template< int N >
struct TupleIter<N,true>
{
template< typename T , typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};
I use a dummy instance of the type of the element at the iterator position and decide via enable_if which function to call. Unfortunately this doesn't work/isn't a nice solution:
The compiler complains about recursive instantiation
The const T& dummy is not a clean solution
I was wondering if enable_if is the right strategy to do the decision and how can one recursively iterate through the std::tuple capturing the first type and keeping all the remaining arguments in vital state. Read through How to split a tuple? but it doesn't do any decision.
How can one implement such a thing in a correct and portable way in C++11?
Well, it was harder than I expected, but this works.
Some things you were doing wrong/that I modified:
You can't evaluate this: std::is_function< typename T::tip >::value, since T::tip is not a type. Even if this could be evaluated, what would happen when T::tip does not exist? Substitution would still fail.
Since you use const references as your tuple's inner types, you had to clean them before trying to find the tip member inside them. By cleaning I mean removing const and removing the reference.
That dummy type stuff was not a good idea, there was no need to use that parameter. You can achieve the same thing using std::tuple_element, which retrieves the i-th type from a tuple.
I modified TupleIter's template parameters to the following, which means:
"TupleIter that processes the index-th type, inside a tuple of size n".
template<size_t index, size_t n>
struct TupleIter;
The whole code is this:
#include <tuple>
#include <iostream>
#include <type_traits>
struct A {
static void tip();
};
struct B {
static void tip();
};
struct Z {
};
// Indicates whether the template parameter contains a static member named tip.
template<class T>
struct has_tip {
template<class U>
static char test(decltype(&U::tip));
template<class U>
static float test(...);
static const bool value = sizeof(test<typename std::decay<T>::type>(0)) == sizeof(char);
};
// Indicates whether the n-th type contains a tip static member
template<size_t n, typename... Ts>
struct nth_type_has_tip {
static const bool value = has_tip<typename std::tuple_element<n, std::tuple<Ts...>>::type>::value;
};
// Generic iteration
template<size_t index, size_t n>
struct TupleIter
{
template< typename... Ts >
typename std::enable_if< nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl)
{
std::cout << "tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}
template< typename... Ts >
typename std::enable_if< !nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl) {
std::cout << "no tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}
};
// Base class, we've reached the tuple end
template<size_t n>
struct TupleIter<n, n>
{
template<typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};
// Helper function that forwards the first call to TupleIter<>::Iter
template<typename... Ts>
void iterate(const std::tuple<Ts...> &tup) {
TupleIter<0, sizeof...(Ts)>::Iter(tup);
}
int main() {
A a;
B b;
Z z;
std::tuple<const A&,const B&,const Z&> tup(a,b,z);
iterate(tup);
}
Here is another take on the question, very similar to mfontanini answer, but showcasing:
boost::fusion::for_each (instead of manually iterate over the tuple).
A variant for implementing has_type using an expression-based SFINAE approach, that I feel a little bit simpler to follow than the usual sizeof trick.
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/fusion/algorithm.hpp>
#include <iostream>
struct nat // not a type
{
private:
nat();
nat(const nat&);
nat& operator=(const nat&);
~nat();
};
template <typename T>
struct has_tip
{
static auto has_tip_imp(...) -> nat;
template <typename U>
static auto has_tip_imp(U&&) -> decltype(U::tip());
typedef decltype(has_tip_imp(std::declval<T>())) type;
static const bool value = !std::is_same<type, nat>::value;
};
struct CallTip
{
template<typename T>
typename std::enable_if<has_tip<T>::value>::type
operator()(T& t) const
{
std::cout << "tip\n";
T::tip();
}
template<typename T>
typename std::enable_if<!has_tip<T>::value>::type
operator()(T& t) const
{
std::cout << "no tip\n";
return;
}
};
struct A {
static void tip(){}
};
struct B {
static void tip(){}
};
struct Z {
};
int main()
{
A a;
B b;
Z z;
boost::tuple<const A&,const B&,const Z&> tpl(a, b, z);
boost::fusion::for_each(tpl, CallTip());
}
Note that if your compiler support variadic template you can use std::tuple instead of boost::tuple inside fusion::for_each by including #include<boost/fusion/adapted/std_tuple.hpp>
Edit :
As pointed by Xeo in the comment, it is possible to simplify a lot the expression-SFINAE approach by removing completely the trait has_tip and simply forward to a little call helper.
The final code is really neat and tight !
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/fusion/algorithm.hpp>
#include <iostream>
struct CallTip
{
template<typename T>
void operator()(const T& t) const
{
call(t);
}
template<class T>
static auto call(const T&) -> decltype(T::tip())
{
std::cout << "tip\n";
T::tip();
}
static void call(...)
{
std::cout << "no tip\n";
}
};
struct A {
static void tip(){}
};
struct B {
static void tip(){}
};
struct Z {
};
int main()
{
A a;
B b;
Z z;
boost::tuple<const A&,const B&,const Z&> tpl(a, b, z);
boost::fusion::for_each(tpl, CallTip());
}

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;
}