Say I have a
struct SMyStruct
{
int MULT;
int VAL;
};
std::map<std::string, SMyStuct*> _idToMyStructMap;
Now I want to calculate total of all SMyStuct, where total is defined as MULT1 *VAL1 + MULT2 *VAL2 for each elements in the idToMyStructMap.
Seems like accumulate function is a natural choice. Please suggest. thanks
No Boost please.... just an 'ld fashion stl
typedef std::map< std::string, SMyStruct* > string_to_struct_t;
int add_to_totals( int total, const string_to_struct_t::value_type& data )
{
return total + data.second->MULT * data.second->VAL;
}
const int total = std::accumulate(
_idToMyStructMap.begin(),
_idToMyStructMap.end(),
0,
add_to_totals );
A variation on the theme would be to define operator+ for your struct, and then just use std::accumulate in its default mode.
int & operator+ (const int &lhs, const SMyStruct &rhs){
return lhs + (rhs.MULT * rhs.VALUE);
}
Then:
std::accumulate(_idToMyStructMap.begin(), _idToMyStructMap.end(), 0);
Of course, if operator+ makes sense in general for your struct, then you'd want to add overloads for using SMyStruct on the left as well, and/or make them templates so that you get functions for int, float, double, long, etc. all in one shot. As jalf mentioned in comments, if operator+ (or this version of it) doesn't make sense in general for your struct, then the other solution is better.
You can also separate the 'take second of pair' functionality from 'calculate MULT*VAL' and 'add something to an accumulator'.
Though you don't need boost to do this, they already created a great deal of a 'functional' programming framework. If you can't use boost, you need some template magic of your own. Not too complicated, though.
#include <map>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>
Now I deem it better to put the multiplication inside the class.
struct SMyStruct
{
int MULT;
int VAL;
long f() const { return MULT*VAL; }
};
Create a generic functor for 'take second of pair':
// a 'take-second' functor
template< typename at_pair >
struct to_second_t : public std::unary_function< at_pair, typename at_pair::second_type > {
const typename at_pair::second_type& operator()( const at_pair & p ) const {
return p.second;
}
};
This looks tricky, but is merely a generic way of saying: 'first do this, then do that with the result':
// compose two functors (simplified)
template< typename at_F, typename at_G >
struct compose_t : public std::unary_function< typename at_F::argument_type, typename at_G::result_type >{
at_F f;
at_G g;
compose_t( at_F& f, at_G& g ): f( f ), g(g) {}
typename at_G::result_type operator()( const typename at_F::argument_type& v ) const {
return g( f( v ) );
}
};
template< typename at_F, typename at_G >
compose_t<at_F, at_G> compose( at_F& f, at_G& g ) { return compose_t<at_F,at_G>( f, g ); }
// compose two functors (a unary one, and a binary one)
//
template< typename at_F, typename at_G >
struct compose2_t : public std::binary_function< typename at_F::first_argument_type, typename at_G::argument_type, typename at_G::result_type >{
at_F f;
at_G g;
compose2_t( at_F& f, at_G& g ): f( f ), g(g) {}
typename at_G::result_type operator()( const typename at_F::first_argument_type& a1, const typename at_G::argument_type& v ) const {
return f( a1, g( v ) );
}
};
template< typename at_F, typename at_G >
compose2_t<at_F, at_G> compose2( at_F& f, at_G& g ) { return compose2_t<at_F,at_G>( f, g ); }
And finally, putting it all in practice:
int main()
{
typedef std::map<int, SMyStruct > tMap;
tMap m;
SMyStruct s = {1,2};
m[1].VAL = 1; m[1].MULT = 3;
m[2].VAL = 2; m[2].MULT = 10;
m[3].VAL = 3; m[3].MULT = 2;
// mind, this is not LISP (yet)
long total = std::accumulate( m.begin(), m.end(), 0,
compose2(
std::plus<int>(),
compose(
to_second_t<tMap::value_type>(),
std::mem_fun_ref( &SMyStruct::f ) ) )
);
std::cout << "total: " << total <<std::endl;
return 0;
}
Related
I've made a function that calculates the sine of a number. It returns the input type if it is std::is_floating_point. But for std::is_integral, it returns a double.
template<class T , typename std::enable_if<std::is_integral<T>::value>::type* = nullptr >
double mysin(const T& t) // note, function signature is unmodified
{
double a = t;
return std::sin(a);
}
template<class T , typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr >
T mysin(const T& t) // note, function signature is unmodified
{
return std::sin(t);
}
Easy enough. Now I'd like this to work for vectors (or arrays) and tuples (or clusters). So that:
(pseudo code:)
std::vector<std::double> a = mysin(std::vector<std::int>);
std::tuple<std::double, std::float> b = mysin(std::tuple<std::int, std::float>);
std::vector<std::tuple<std::double, std::float>> c = mysin(std::vector<std::tuple<std::int, std::float>>);
std::tuple<std::vector<std::double>, std::float> d = mysin(std::tuple<std::vector<std::int>, std::float>);
std::tuple<std::tuple<std::double, std::vector<std::double>>, std::float>> e = mysin(std::tuple<std::tuple<std::int, std::vector<std::int>>, std::float>>);
and so on...
In most examples about tuple templates, the function either has no return value, returns an accumulated value, or has the same return type as the input.
I've experimented a lot with these topics (among others):
Traversing nested C++11 tuple , c++11: building a std::tuple from a template function , How to make a function that zips two tuples in C++11 (STL)?
The last one has been especially useful. I've got this working for tuples, but not for recursive tuples (tuples in tuples).
Eventually (if this is possible at all), I'll have to make a mycos, mytan, myasin, etc. Using gcc 4.9.2.
**EDIT:**So this is what I came up with after Yakk's suggestions, and a little tweaking:
#include <utility>
#include <vector>
#include <memory>
#include <typeinfo> // used for typeid
#include <tuple>
#include <cstdlib> // for math functions?
#include <cmath> // for math functions
#include <type_traits> // for std::enable_if
template<class T , typename std::enable_if<std::is_integral<T>::value>::type* = nullptr >
double mysin(const T& t) { // note, function signature is unmodified
double a = t;
return std::sin(a);
// printing a debug string here will
// print tuple elements reversed!!
}
template<class T , typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr >
T mysin(const T& t) {// note, function signature is unmodified
// printing a debug string here will
// print tuple elements reversed!!
return std::sin(t);
}
struct sine_t {
template<class T>
auto operator()(T&&t)const->
decltype(mysin(std::declval<T>())) {
return mysin(std::forward<T>(t));
}
};
template<class F>
struct vectorize {
template<class T,
class R=std::vector< std::result_of_t< vectorize<F>(T const&) > >
>
R operator()( std::vector<T> const& v ) const {
R ret;
ret.reserve(v.size());
for( auto const& e : v ) {
ret.push_back( vectorize<F>{}(e) );
}
return ret;
}
template<
class X,
class R=std::result_of_t< F(X const&) >
>
R operator()( X const& x ) const {
return F{}(x);
}
template<
class R,
class... Ts,
size_t... Is
>
R tup_help( std::index_sequence<Is...>, std::tuple<Ts...> const& t ) const {
return std::make_tuple( vectorize<F>{}(std::get<Is>(t))... );
}
template<
class... Ts,
class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
>
R operator()( std::tuple<Ts...> const& t ) const {
return tup_help<R>( std::index_sequence_for<Ts...>{}, t );
}
};
//+++++++++++++++++++++++++++++++++++++++++
int main() {
std::vector<int> a = {1 ,2};
std::tuple<int, double, int, double> b (42, -3.14, 42, -3.14);
auto c = vectorize<sine_t>()(a);
auto d = vectorize<sine_t>()(b);
std::vector<std::tuple<int, int> > e {std::make_tuple(1 ,2)};
//This does not not work:
//auto f = vectorize<sine_t>()(e);
//This works:
std::tuple<std::vector<int> > g ( a );
auto f = vectorize<sine_t>()(g);
return 0;
}
This works. Needs c++14.
First an overload set object. This is useful because it lets us pass around the entire overload set as a single object:
struct sine_t {
template<class T>
auto operator()(T&&t)const->
decltype(mysin(std::declval<T>()))
{ return mysin(std::forward<T>(t)); }
};
next, we want to "vectorize" a given function object.
We'll start simple:
template<class F>
struct vectorize {
template<class T, class R=std::vector< std::result_of_t< F(T const&) > >>
R operator()( std::vector<T> const& v ) const {
R ret;
ret.reserve(v.size());
for( auto const& e : v ) {
ret.push_back( F{}(e) );
}
return ret;
}
template<class X, class R=std::result_of_t< F(X const&) >>
R operator()( X const& x ) const {
return F{}(x);
}
};
this supports 1 level recursion, and only on std::vector.
To allow infinite recursion of nested std::vectors, we modify the operator() overload for std::vector:
template<
class T,
class R=std::vector< std::result_of_t< vectorize<F>(T const&) > >
>
R operator()( std::vector<T> const& v ) const {
R ret;
ret.reserve(v.size());
for( auto const& e : v ) {
ret.push_back( vectorize<F>{}(e) );
}
return ret;
}
and now we support std::vector<std::vector<int>>.
For tuple support, we add 2 functions. The first one has this signature:
template<
class... Ts,
class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
>
R operator()( std::tuple<Ts...> const& t ) const
which gets us our return value (half the battle). To actually do the mapping, use the indexes trick:
template<
class R,
class... Ts,
size_t... Is
>
R tup_help( std::index_sequence<Is...>, std::tuple<Ts...> const& t ) const
{
return std::make_tuple( vectorize<F>{}(std::get<Is>(t))... );
}
template<
class... Ts,
class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
>
R operator()( std::tuple<Ts...> const& t ) const {
return tup_help<R>( std::index_sequence_for<Ts...>{}, t );
}
similar code for std::array and raw C arrays should work (converting the raw C array to a std::array naturally).
std::index_sequence etc is C++14, but easy to write a version that supports 100s of elements in C++11. (A version that supports large arrays takes more work). The result_of_t alias (and any similar) are also C++14, but the aliases are easy to write in C++11, or you can just typename std::result_of<?>::type verbose explosion.
In the end, you vectorize<sine_t>{} and pass in whatever.
If you want a function instead of a function object, simply have it delegate the work to vectorize<sine_t>.
I would like to use templates for optimization as described here. However, with a growing number of bool template arguments, instantiating the template might have too many branches. And it gets even more branchy if you use larger enums instead of bools.
#include <iostream>
using namespace std;
template <bool b1, bool b2>
int HeavyLoop_impl(int arg)
{
for (int i = 0; i < 10000000; i++)
{
// b1 is known at compile-time, so this branch will be eliminated
if (b1) { arg += 1; }
else { arg += 2; }
// b2 is known at compile-time, so this branch will be eliminated
if (b2) { arg += 10; }
else { arg += 20; }
}
return arg;
}
// This function could be generated automatically
void HeavyLoop(bool b1, bool b2, int arg)
{
int res;
if (b1) {
if (b2) { res = HeavyLoop_impl<true, true>(arg); }
else { res = HeavyLoop_impl<true, false>(arg); }
} else {
if (b2) { res = HeavyLoop_impl<false, true>(arg); }
else { res = HeavyLoop_impl<false, false>(arg); }
}
cout << "res: "<<res<<endl;
}
int main(int argc, char**argv)
{
bool b1 = true;
bool b2 = false;
int arg = 0;
HeavyLoop(b1, b2, arg);
return 0;
}
Is there any way to automatically generate the HeavyLoop function? I would like something like this:
vars_to_template_function<bool, bool>(HeavyLoop_impl, b1, b2, arg);
Would that be possible somehow? Thanks for any hints.
Note: this is only a very simplified example. The actual loop is is of course more complicated :o)
I decided to have some more fun with the code, here's an improved version over my first attempt which has the following benefits:
Supports enum types
Explicitly specify how many parameters should be converted
Generic implementation for the complicated part, one small helper for each function that uses it.
The code:
#include <iostream>
#include <utility>
#include <type_traits>
// an enum we would like to support
enum class tribool { FALSE, TRUE, FILE_NOT_FOUND };
// declare basic generic template
// (independent of a specific function you'd like to call)
template< template< class > class CB, std::size_t N, typename = std::tuple<> >
struct var_to_template;
// register types that should be supported
template< template< class > class CB, std::size_t N, typename... Cs >
struct var_to_template< CB, N, std::tuple< Cs... > >
{
// bool is pretty simple, there are only two values
template< typename R, typename... Args >
static R impl( bool b, Args&&... args )
{
return b
? var_to_template< CB, N-1, std::tuple< Cs..., std::true_type > >::template impl< R >( std::forward< Args >( args )... )
: var_to_template< CB, N-1, std::tuple< Cs..., std::false_type > >::template impl< R >( std::forward< Args >( args )... );
}
// for each enum, you need to register all its values
template< typename R, typename... Args >
static R impl( tribool tb, Args&&... args )
{
switch( tb ) {
case tribool::FALSE:
return var_to_template< CB, N-1, std::tuple< Cs..., std::integral_constant< tribool, tribool::FALSE > > >::template impl< R >( std::forward< Args >( args )... );
case tribool::TRUE:
return var_to_template< CB, N-1, std::tuple< Cs..., std::integral_constant< tribool, tribool::TRUE > > >::template impl< R >( std::forward< Args >( args )... );
case tribool::FILE_NOT_FOUND:
return var_to_template< CB, N-1, std::tuple< Cs..., std::integral_constant< tribool, tribool::FILE_NOT_FOUND > > >::template impl< R >( std::forward< Args >( args )... );
}
throw "unreachable";
}
// in theory you could also add int, long, ... but
// you'd have to switch on every possible value that you want to support!
};
// terminate the recursion
template< template< class > class CB, typename... Cs >
struct var_to_template< CB, 0, std::tuple< Cs... > >
{
template< typename R, typename... Args >
static R impl( Args&&... args )
{
return CB< std::tuple< Cs... > >::template impl< R >( std::forward< Args >( args )... );
}
};
// here's your function with the template parameters
template< bool B, tribool TB >
int HeavyLoop_impl( int arg )
{
for( int i = 0; i < 10000000; i++ ) {
arg += B ? 1 : 2;
arg += ( TB == tribool::TRUE ) ? 10 : ( TB == tribool::FALSE ) ? 20 : 30;
}
return arg;
}
// a helper class, required once per function that you'd like to forward
template< typename > struct HeavyLoop_callback;
template< typename... Cs >
struct HeavyLoop_callback< std::tuple< Cs... > >
{
template< typename R, typename... Args >
static R impl( Args&&... args )
{
return HeavyLoop_impl< Cs::value... >( std::forward< Args >( args )... );
}
};
// and here, everything comes together:
int HeavyLoop( bool b, tribool tb, int arg )
{
// you provide the helper and the number of arguments
// that should be converted to var_to_template<>
// and you provide the return type to impl<>
return var_to_template< HeavyLoop_callback, 2 >::impl< int >( b, tb, arg );
}
int main()
{
bool b = true;
tribool tb = tribool::FALSE;
int arg = 0;
int res = HeavyLoop( b, tb, arg );
std::cout << "res: " << res << std::endl;
return 0;
}
And here's a live example in case you want to play with it.
Here's how you can do it:
#include <iostream>
using namespace std;
template <bool b1, bool b2>
struct HeavyLoopImpl
{
static int func(int arg)
{
for (int i = 0; i < 10000000; i++) {
arg += b1 ? 1 : 2;
arg += b2 ? 10 : 20;
}
return arg;
}
};
template <template<bool...> class Impl,bool...Bs>
struct GenericJump
{
template<typename... Args>
static int impl(Args&&... args)
{
return Impl<Bs...>::func(std::forward<Args>(args)...);
}
template<typename... Args>
static int impl(bool b, Args&&... args)
{
return b
? GenericJump<Impl,Bs...,true >::impl(std::forward<Args>(args)...)
: GenericJump<Impl,Bs...,false>::impl(std::forward<Args>(args)...);
}
};
int HeavyLoop(bool b1, bool b2, int arg)
{
return GenericJump<HeavyLoopImpl>::impl(b1,b2,arg);
}
int main()
{
bool b1 = true;
bool b2 = false;
int arg = 0;
int res = HeavyLoop(b1, b2, arg);
cout << "res: "<<res<<endl;
return 0;
}
This is basically Daniels solution, but it allows you to use functions other than HeavyLoop_impl() as implementation. Only being able to call a single template function kind of defeats the purpose of being a generic solution. The GenericJump template class can call other functions also. You only have to change the HeavyLoop_impl() template function into a template class with a static function func(). It works marvellously. It compiles with gcc 4.7.3 and gives the correct output.
The ideal generic solution really depends on what you want to vary. The possibilities for variation are:
The number of branches, and the types of the variables being branched on.
The operation to be performed and the number and types of its arguments.
I would recommend not making an completely generic solution unless you really need to vary all of those things. Consider only the things you want to vary and your life will be much easier.
Assuming that the total number of branches is less than 2^64, you can use a switch statement to do the dispatch. The following solution demonstrates how this could work:
template<unsigned permutation>
struct Permutation
{
static_assert(permutation < 4, "permutation must be in the range [0, 4)");
static const bool b1 = permutation & (1 << 0);
static const bool b2 = permutation & (1 << 1);
};
unsigned makePermutation(bool b1, bool b2)
{
return (b1 << 0) | (b2 << 1);
}
template<unsigned p>
int HeavyLoop_impl(int arg)
{
return HeavyLoop_impl<Permutation<p>::b1, Permutation<p>::b2>(arg);
}
int HeavyLoop_impl(unsigned permutation, int arg)
{
switch(permutation)
{
case 0: return HeavyLoop_impl<0>(arg);
case 1: return HeavyLoop_impl<1>(arg);
case 2: return HeavyLoop_impl<2>(arg);
case 3: return HeavyLoop_impl<3>(arg);
}
}
[Note: It would be trivial to use Boost.Preprocessor to generate the above switch statement.]
void HeavyLoop(bool b1, bool b2, int arg)
{
int res = HeavyLoop_impl(makePermutation(b1, b2), arg);
cout << "res: "<<res<<endl;
}
I think the best answer to your question is actually not to generate it automatically and leave it how you already have it in the question.
Making an automatic template function to generate the middle ground just obfuscates the invariant switching you're doing in the first place.
I much prefer to try to understand how the middle layer works in your question, than any of the answers people have offered for you.
I have a similar example. In my case I can apply a number of different operations between an array of values. The arrays are equal size. However I also have a structure that maps sub-ranges of the array with weight values that affect my operations.
So for instance, I might be working with arrays of 100 values, and have ranges with weights like this:
[0,25] rangeWeight = 0
[26,35] rangeWeight = 0.25
[36,50] rangeWeight = 0.5
[51,99] rangeWeight = 1.0
So each operation looks something like (pseudo):
for each subrange:
alias to the dst buffer
alias to the src buffer
determine the number of elements in the range
if there's any
weight = weightPassedIn * rangeWeight;
Op(dst, src, weight, numElements);
For me, there were several optimizations involving whether or not the destination is touched or not (if it was still at the cleared value, some assumptions can be made to simplify the math per operation), Also if the weight happens to be full, 1.0, there are other shortcuts.
At first I was writing the same loop over and over with all of the same setup, and once I refactored all the loops around each op into functions, I pretty much naturally had the form of your invariant wrapper. There actually turned out to be several wrappers which mainly just wrap the high level operation happening inside the loop, and otherwise just handle the individual optimizations like this:
if (weight == 1.0f)
{
if ( arrayIsCleared )
Blend<BlendOpSet, true, false>(otherBuff, subRangesMask, 1.0f);
else
Blend<BlendOpAccumulate, true, false>(otherBuff, subRangesMask, 1.0f);
}
else
{
if ( arrayIsCleared )
Blend<BlendOpSet, false, false>(otherBuff, subRangesMask, weight);
else
Blend<BlendOpAccumulate, false, false>(otherBuff, subRangesMask, weight);
}
Have you considered passing a function as template argument? This way you can tailor your inner loop to your own wishes.
Function passed as template argument
However, the function call will have a small overhead.
Here is another solution with boost::hana, which can handle also enums:
#include <cstdio>
#include <type_traits>
#include <boost/hana.hpp>
namespace hana = boost::hana;
template <typename F, typename TArgs, typename TIn, typename TOut>
void fun_arg_combinations_impl(F&& f, TArgs targs, TIn tin, TOut tout) {
if constexpr (hana::is_empty(tin)) {
hana::unpack(tout, f);
} else {
hana::for_each(hana::front(tin), [&](auto v){
if (v == hana::front(targs)) {
fun_arg_combinations_impl(f, hana::drop_front(targs), hana::drop_front(tin), hana::append(tout, v));
}
});
}
}
template <typename F, typename TArgs, typename TIn>
void fun_arg_combinations(F&& f, TArgs targs, TIn tin) {
fun_arg_combinations_impl(f, targs, tin, hana::tuple<>());
}
enum Shape {LINE, CIRCLE, SQUARE};
int main()
{
auto f_heavy_loop = [](auto b1t, auto b2t, auto st) {
constexpr bool b1 = decltype(b1t)::value;
constexpr bool b2 = decltype(b2t)::value;
constexpr Shape s = decltype(st )::value;
printf("out:%d %d %d\n", b1, b2, s);
};
//constexpr auto bools = hana::make_tuple(std::true_type{}, std::false_type{});
constexpr auto bools = hana::tuple<std::true_type, std::false_type>{};
constexpr auto shapes = hana::tuple<
std::integral_constant<Shape, LINE>,
std::integral_constant<Shape, CIRCLE>,
std::integral_constant<Shape, SQUARE>>{};
// Using volatile to not allow the compiler to optimize for hard-coded values
volatile bool b1 = true;
volatile bool b2 = false;
volatile Shape s = SQUARE;
fun_arg_combinations(
f_heavy_loop,
hana::make_tuple(b1 , b2 , s ),
hana::make_tuple(bools, bools, shapes));
}
b1, b2 and s inside the f_heavy_loop() lambda are all constexpr, so we can use if constexpr on them.
output:
out:1 0 2
Have a look at the generated assembly here: https://godbolt.org/z/nsF2l5
#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.
Is there a way in C++ to determine function signature of a callable object?
Consider following:
template< typename F >
void fun(F f)
{
// ...
}
Lets assume that fun is called only with callable "things".
Inside of fun I want to know what is the signature of function f. That should work with function pointers, references, wrappers, lambdas, binds, function objects (providing they have only one operator ()) and so on. I'm limited with Visual Studio 2010 SP 1 but am interested in standard solutions even if not working on that compiler.
(A function signature is Return_Type ([Arg1_Type [, Arg2_Type [, ... ] ] ]); same as given to std::function/boost::function.)
A partial solution of knowing at least the return value of f is of some value to. (I have tried std::result_of but couldn't get it to work in any case I tried.)
On C++0x compliant compilers, you can at least get the result type of f() by using decltype(f()). Visual C++ 2010 should support decltype, though I haven't checked it myself yet. As for getting the argument types, I'm not sure if there's a way that would work with function pointers.
Edit
Boost.Function seems to have it figured out, at least on some compilers (it doesn't work on old versions of VC++ or Borland C++ for instance). It can wrap function pointers and extract arguments for them. The solution seems quite complex however, and it involves defining multiple templates with Boost.PP. If you feel like trying to re-implement everything you can certainly try that, but I think you can also just use a dummy Boost.Function wrapper to make things easier, e.g. boost::function<decltype(f)>::second_argument_type to get the second argument type.
You may look at Boost Function Types:
http://www.boost.org/doc/libs/1_46_1/libs/function_types/doc/html/boost_functiontypes/introduction.html
While trying to solve this I came up with following partial solution:
#include <cstdlib>
#include <functional>
#include <iostream>
#include <typeinfo>
#include <boost/bind.hpp>
#include <boost/function.hpp>
template< typename T >
struct identity
{
typedef T type;
};
// ----------
// Function signature metafunction implementation
// Also handler for function object case
// ----------
template< typename T >
struct function_signature_impl
: function_signature_impl< decltype( &T::operator() ) >
{
};
// ----------
// Function signature specializations
// ----------
template< typename R >
struct function_signature_impl< R () >
: identity< R () >
{
};
template< typename R, typename A1 >
struct function_signature_impl< R ( A1 ) >
: identity< R ( A1 ) >
{
};
template< typename R, typename A1, typename A2 >
struct function_signature_impl< R ( A1, A2 ) >
: identity< R ( A1, A2 ) >
{
};
// ----------
// Function pointer specializations
// ----------
template< typename R >
struct function_signature_impl< R ( * )() >
: function_signature_impl< R () >
{
};
template< typename R, typename A1 >
struct function_signature_impl< R ( * )( A1 ) >
: function_signature_impl< R ( A1 ) >
{
};
// ----------
// Member function pointer specializations
// ----------
template< typename C, typename R >
struct function_signature_impl< R ( C::* )() >
: function_signature_impl< R () >
{
};
template< typename C, typename R, typename A1 >
struct function_signature_impl< R ( C::* )( A1 ) >
: function_signature_impl< R ( A1 ) >
{
};
template< typename C, typename R >
struct function_signature_impl< R ( C::* )() const >
: function_signature_impl< R () >
{
};
template< typename C, typename R, typename A1 >
struct function_signature_impl< R ( C::* )( A1 ) const >
: function_signature_impl< R ( A1 ) >
{
};
// ----------
// Function signature metafunction
// ----------
template< typename T >
struct function_signature
: function_signature_impl< T >
{
};
// ----------
// Tests
// ----------
template< typename F >
void test( F f )
{
typedef function_signature< F >::type signature_type;
std::cout << typeid( F ).name() << std::endl;
std::cout << '\t' << typeid( signature_type ).name() << std::endl;
std::cout << std::endl;
}
int foo( int )
{
return 0;
}
struct bar
{
int operator ()( int )
{
return 0;
}
};
struct cbar
{
int operator ()( int ) const
{
return 0;
}
};
struct abar1
{
int operator ()( int ) const
{
return 0;
}
int operator ()( int )
{
return 0;
}
};
struct abar2
{
int operator ()( int )
{
return 0;
}
int operator ()( double )
{
return 0;
}
};
struct mem
{
int f( int ) const
{
return 0;
}
};
int main()
{
test(
[]( int ) -> int { return 0; }
);
test(
foo
);
test(
&foo
);
test(
bar()
);
test(
cbar()
);
test(
std::function< int ( int ) >( &foo )
);
test(
boost::function< void ( int ) >( &foo )
);
/*
test(
std::bind( &mem::f, mem(), std::placeholders::_1 )
);
*/
/*
test(
boost::bind( &mem::f, mem(), _1 )
);
*/
/*
test(
abar1()
);
*/
/*
test(
abar2()
);
*/
return EXIT_SUCCESS;
}
(No code for checking agains inproper arguments was added.)
The idea is that function_signature< decltype( f ) >::type should be the signature of a call of f( ... ) where that "..." is the signature. This means in particular that pointer to member function is an invalid argument here (although the code does not check against this) since such pointer cannot be "called" directly.
At the end are tests which fail (in VS 2010). All due to operator () being overloaded. And this makes that code mostly useless as it will not work with the result of bind. But maybe it can be further developed.
Answer to André Bergner's query:
function_signature_impl never derives from itself. It is a type template which only means a loosely coupled family of actual types. But the actual types (even thou they belong to the same family) are distinct types.
The &T::operator() is a pointer to a call operator (operator()) of type T – obviously. Basically just a member function pointer (where the member function happens to be a call operator). While decltype of it is the type of that pointer. This might seem insignificant (especially that type_info::name of both shows the same) but for templates it does matter since one is a pointer while the other is a type (apparently).
This “case” is needed to cover for functors (types which objects are “callable”). Note that this unspecialized function_signature_impl is used only if the template argument T doesn’t match anything else among the listed “cases”.
I hope I got it right after that long time. Although I’m not sure if I ever truly and fully understood it. The code was a bit result of experimenting.
This answer was just given to me by SlashLife on freenode ##c++:
template <typename T, typename Signature>
struct signature_impl;
template <typename T, typename ReturnType, typename... Args>
struct signature_impl<T, ReturnType(T::*)(Args...)>
{
using type = ReturnType(Args...);
};
template <typename T>
using signature_t = signature_impl<T, decltype(&T::operator())>;
The caveats are that it only works if there is a unique operator() and it doesn't work for lambdas.
You can use std::is_invocable_r
Let's say that I have a parameter pack I'm unrolling, e.g.
template<typename... P> void f(P...&& args) {
some_other_func(std::forward<P>(args)...);
}
Now let's say that I have some other minor function that these objects need to go through.
template<typename T> T&& some_func(T&& ref) {
// replace with actual logic
return std::forward<T>(ref);
}
I would normally just replace with
template<typename... P> void f(P...&& args) {
some_other_func(some_func(args)...);
}
But what do I do if some_func requires more information about the parameter than just it's type, like for example, it's position numerically in the parameter pack? So that instead of expanding to
some_other_func(some_func(arg1), some_func(arg2));
I could mke it expand to
some_other_func(some_func(arg1, 1), some_func(arg2, 2));
for example?
I know I've solved this before but can't recall how. Oh well, here's a fresh look.
The sequence of numbers can be translated into the argument sequence using std::get, so it is more fundamental. So, assuming that I need to implement some kind of custom tool, a number pack generator seems like a good choice.
(Gah, this was incredibly tedious. I did peek at Howard's answer and learned about forward_as_tuple, but that function doesn't even exist yet on my compiler or ideone.com, so blah. There are a lot of things I still need to get straight, and this is certainly one of the worst functional languages ever invented.)
http://ideone.com/u5noV
#include <tuple>
// Generic pack array (metacontainer)
template< typename T, T ... seq > struct value_sequence {
// Append a value to the array (metafunction)
template< T val > struct append
{ typedef value_sequence< T, seq..., val > type; };
};
// Generate a sequential array (metafunction)
template< size_t N >
struct index_sequence {
typedef typename index_sequence< N - 1 >::type
::template append< N - 1 >::type type;
};
template<>
struct index_sequence< 0 >
{ typedef value_sequence< size_t > type; };
// Generate indexes up to size of given tuple (metafunction)
template< typename T >
struct index_tuple {
typedef typename index_sequence< std::tuple_size< T >::value
>::type type;
};
// The magic function: passes indexes, makes all the function calls
template< typename F, typename G,
typename T, size_t ... N >
void compose_with_indexes_helper( F f, G g, T args,
value_sequence< size_t, N ... > ) {
f( g( std::get< N >( args ), N ) ... );
}
template< typename F, typename G, typename ... T >
void compose_with_indexes( F f, G g, T && ... args ) {
typedef std::tuple< T && ... > tuple_t;
compose_with_indexes_helper
// forwarding seems broken on ideone.com/GCC 4.5.1, work around.
// ( f, g, std::forward_as_tuple( std::forward( args ) ... ) );
( f, g, tuple_t( args ... ), typename index_tuple< tuple_t >::type() );
}
It is a little convoluted. But here is a working prototype of your code using several private utilities of libc++, found in
<__tuple>, and <tuple>.
#include <iostream>
#include <tuple>
template<typename T>
int
some_func(T&& ref, size_t I)
{
std::cout << "ref = " << ref << ", I = " << I << '\n';
return 0;
}
template<typename... T, size_t ...Indx>
void
some_other_func(std::tuple<T...> ref, std::__tuple_indices<Indx...>) {
// replace with actual logic
std::__swallow(some_func(std::get<Indx>(ref), Indx)...);
}
template<typename... P>
void
f(P&&... args)
{
some_other_func(std::forward_as_tuple<P...>(std::forward<P>(args)...),
typename std::__make_tuple_indices<sizeof...(P)>::type());
}
int main()
{
f("zero", "one", "two", "three");
}
ref = zero, I = 0
ref = one, I = 1
ref = two, I = 2
ref = three, I = 3