#include <iostream>
#include <tuple>
#include <utility>
#include <type_traits>
// C++17 std::apply
template < typename F, typename Tuple, size_t ... Is >
auto apply_impl ( F&& f, Tuple&& tuple, const std:: index_sequence < Is...> & ) {
return ( std:: forward < F> ( f) ) ( std:: get < Is> ( std:: forward < Tuple> ( tuple) ) ...) ;
}
template < typename Fn, typename Tuple>
auto apply ( Fn&& fn, Tuple&& tuple) { // Invoke the Callable object f with a tuple of arguments.
return apply_impl( std:: forward < Fn> ( fn) , std:: forward < Tuple> ( tuple) , std:: make_index_sequence < std:: tuple_size < std:: decay_t < Tuple>> :: value > ( ) ) ;
}
// The subtuple that skips the first 'Skip' components of 'tuple' and then takes the next 'Take' components.
template < std:: size_t Skip, std:: size_t Take>
struct GetSubtuple {
template < typename Tuple>
static auto get ( const Tuple& tuple) {
return std:: tuple_cat ( std:: make_tuple ( std:: get < Skip> ( tuple) ) , GetSubtuple< Skip+ 1 , Take- 1 > :: get ( tuple) ) ;
}
} ;
template < std:: size_t Skip>
struct GetSubtuple< Skip, 0 > {
template < typename Tuple>
static std:: tuple <> get ( const Tuple& ) { return std:: tuple <> ( ) ; }
} ;
// Compile-time partial sums. But here is it special. For example, PartialSums<5,10,20>::type is to be P<0,5,15>. We want it to always start with 0, and always ignore the last term in the pack.
template < typename T, typename Output, T LastSum, T...> struct PartialSumsHelper;
template < typename T, template < T...> class P, T... Is , T LastSum, T First, T... Rest >
struct PartialSumsHelper< T, P< Is...> , LastSum, First, Rest...> : PartialSumsHelper< T, P< Is..., LastSum + First> , LastSum + First, Rest...> { } ;
template < typename T, template < T...> class P, T... Is , T LastSum, T Last>
struct PartialSumsHelper< T, P< Is...> , LastSum, Last> {
using type = P< Is...> ; // We don't want to add the last term to the partial sums in this program.
} ;
template < typename T, T... Is >
struct PartialSums {
template < T...> struct P;
using type = typename PartialSumsHelper< T, P< 0 > , 0 , Is...> :: type ; // Here we want the first partial sum to be 0 rather than the first value in Is...
} ;
template < typename Sums, std:: size_t ... Is > struct MultiFunction;
template < template < std:: size_t ...> class P, size_t ... Sums , std:: size_t ... Is >
struct MultiFunction< P< Sums...> , Is...> {
template < typename FunctionTuple, typename ArgsTuple>
static auto execute ( const FunctionTuple& functionTuple, const ArgsTuple& argsTuple) {
return executeHelper( functionTuple, std:: make_index_sequence < std:: tuple_size < FunctionTuple> :: value > { } , GetSubtuple< Sums, Is> :: get ( argsTuple) ...) ;
}
private :
template < typename FunctionTuple, std:: size_t ... Js , typename ... TupleArgs >
static auto executeHelper ( const FunctionTuple& functionTuple, const std:: index_sequence < Js...> & , const TupleArgs& ... tupleArgs ) {
const auto tupleOfTuples = std:: make_tuple ( tupleArgs...) ;
// const int a[] = {(apply(std::get<Js>(functionTuple), std::get<Js>(tupleOfTuples)), 0)...}; ///// Just a Test. Order of function call correct.
return std:: make_tuple ( apply( std:: get < Js> ( functionTuple) , std:: get < Js> ( tupleOfTuples) ) ...) ; ///// order of function call reversed. Need to define make_tuple_left_to_right which returns the same as make_tuple but calls from left to right.
}
} ;
template < std:: size_t ... Is , typename ArgsTuple, typename ... Fs >
auto multiFunction ( const ArgsTuple& argsTuple, Fs... fs ) {
return MultiFunction< typename PartialSums< std:: size_t , Is...> :: type , Is...> :: execute ( std:: make_tuple ( fs...) , argsTuple) ;
}
// Testing
int foo ( int , char ) { std:: cout << "foo\n " ; return 0 ; }
double bar ( bool , double , long ) { std:: cout << "bar\n " ; return 3.5 ; }
bool baz ( char , short , float ) { std:: cout << "baz\n " ; return true ; }
int main( ) {
const auto tuple = std:: make_tuple ( 5 , 'a' , true , 3.5 , 1000 , 't' , 2 , 5.8 ) ;
const auto t = multiFunction< 2 ,3 ,3 > ( tuple, foo, bar, baz) ;
std:: cout << std:: boolalpha << std:: get < 0 > ( t) << ' ' << std:: get < 1 > ( t) << ' ' << std:: get < 2 > ( t) << '\n ' ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx1dGlsaXR5PgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgovLyBDKysxNyBzdGQ6OmFwcGx5CnRlbXBsYXRlIDx0eXBlbmFtZSBGLCB0eXBlbmFtZSBUdXBsZSwgc2l6ZV90Li4uIElzPgphdXRvIGFwcGx5X2ltcGwgKEYmJiBmLCBUdXBsZSYmIHR1cGxlLCBjb25zdCBzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPiYpIHsKICAJcmV0dXJuIChzdGQ6OmZvcndhcmQ8Rj4oZikpKHN0ZDo6Z2V0PElzPihzdGQ6OmZvcndhcmQ8VHVwbGU+KHR1cGxlKSkuLi4pOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRm4sIHR5cGVuYW1lIFR1cGxlPgphdXRvIGFwcGx5IChGbiYmIGZuLCBUdXBsZSYmIHR1cGxlKSB7ICAvLyBJbnZva2UgdGhlIENhbGxhYmxlIG9iamVjdCBmIHdpdGggYSB0dXBsZSBvZiBhcmd1bWVudHMuIAogIAlyZXR1cm4gYXBwbHlfaW1wbChzdGQ6OmZvcndhcmQ8Rm4+KGZuKSwgc3RkOjpmb3J3YXJkPFR1cGxlPih0dXBsZSksIHN0ZDo6bWFrZV9pbmRleF9zZXF1ZW5jZTxzdGQ6OnR1cGxlX3NpemU8c3RkOjpkZWNheV90PFR1cGxlPj46OnZhbHVlPigpKTsKfQoKLy8gVGhlIHN1YnR1cGxlIHRoYXQgc2tpcHMgdGhlIGZpcnN0ICdTa2lwJyBjb21wb25lbnRzIG9mICd0dXBsZScgYW5kIHRoZW4gdGFrZXMgdGhlIG5leHQgJ1Rha2UnIGNvbXBvbmVudHMuIAp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgU2tpcCwgc3RkOjpzaXplX3QgVGFrZT4Kc3RydWN0IEdldFN1YnR1cGxlIHsKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUdXBsZT4KICAgIHN0YXRpYyBhdXRvIGdldCAoY29uc3QgVHVwbGUmIHR1cGxlKSB7CgkJcmV0dXJuIHN0ZDo6dHVwbGVfY2F0KCBzdGQ6Om1ha2VfdHVwbGUoc3RkOjpnZXQ8U2tpcD4odHVwbGUpKSwgR2V0U3VidHVwbGU8U2tpcCsxLCBUYWtlLTE+OjpnZXQodHVwbGUpICk7Cgl9Cn07Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgU2tpcD4Kc3RydWN0IEdldFN1YnR1cGxlPFNraXAsIDA+IHsKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUdXBsZT4KICAgIHN0YXRpYyBzdGQ6OnR1cGxlPD4gZ2V0IChjb25zdCBUdXBsZSYpIHsgcmV0dXJuIHN0ZDo6dHVwbGU8PigpOyB9Cn07CgovLyBDb21waWxlLXRpbWUgcGFydGlhbCBzdW1zLiAgQnV0IGhlcmUgaXMgaXQgc3BlY2lhbC4gIEZvciBleGFtcGxlLCBQYXJ0aWFsU3Vtczw1LDEwLDIwPjo6dHlwZSBpcyB0byBiZSBQPDAsNSwxNT4uICBXZSB3YW50IGl0IHRvIGFsd2F5cyBzdGFydCB3aXRoIDAsIGFuZCBhbHdheXMgaWdub3JlIHRoZSBsYXN0IHRlcm0gaW4gdGhlIHBhY2suCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBPdXRwdXQsIFQgTGFzdFN1bSwgVC4uLj4gc3RydWN0IFBhcnRpYWxTdW1zSGVscGVyOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHRlbXBsYXRlIDxULi4uPiBjbGFzcyBQLCBULi4uIElzLCBUIExhc3RTdW0sIFQgRmlyc3QsIFQuLi4gUmVzdD4Kc3RydWN0IFBhcnRpYWxTdW1zSGVscGVyPFQsIFA8SXMuLi4+LCBMYXN0U3VtLCBGaXJzdCwgUmVzdC4uLj4gOiBQYXJ0aWFsU3Vtc0hlbHBlcjxULCBQPElzLi4uLCBMYXN0U3VtICsgRmlyc3Q+LCBMYXN0U3VtICsgRmlyc3QsIFJlc3QuLi4+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHRlbXBsYXRlIDxULi4uPiBjbGFzcyBQLCBULi4uIElzLCBUIExhc3RTdW0sIFQgTGFzdD4Kc3RydWN0IFBhcnRpYWxTdW1zSGVscGVyPFQsIFA8SXMuLi4+LCBMYXN0U3VtLCBMYXN0PiB7Cgl1c2luZyB0eXBlID0gUDxJcy4uLj47ICAvLyBXZSBkb24ndCB3YW50IHRvIGFkZCB0aGUgbGFzdCB0ZXJtIHRvIHRoZSBwYXJ0aWFsIHN1bXMgaW4gdGhpcyBwcm9ncmFtLgp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIFQuLi4gSXM+CnN0cnVjdCBQYXJ0aWFsU3VtcyB7Cgl0ZW1wbGF0ZSA8VC4uLj4gc3RydWN0IFA7Cgl1c2luZyB0eXBlID0gdHlwZW5hbWUgUGFydGlhbFN1bXNIZWxwZXI8VCwgUDwwPiwgMCwgSXMuLi4+Ojp0eXBlOyAgLy8gSGVyZSB3ZSB3YW50IHRoZSBmaXJzdCBwYXJ0aWFsIHN1bSB0byBiZSAwIHJhdGhlciB0aGFuIHRoZSBmaXJzdCB2YWx1ZSBpbiBJcy4uLgp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFN1bXMsIHN0ZDo6c2l6ZV90Li4uIElzPiBzdHJ1Y3QgTXVsdGlGdW5jdGlvbjsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8c3RkOjpzaXplX3QuLi4+IGNsYXNzIFAsIHNpemVfdC4uLiBTdW1zLCBzdGQ6OnNpemVfdC4uLiBJcz4Kc3RydWN0IE11bHRpRnVuY3Rpb248UDxTdW1zLi4uPiwgSXMuLi4+IHsKCXRlbXBsYXRlIDx0eXBlbmFtZSBGdW5jdGlvblR1cGxlLCB0eXBlbmFtZSBBcmdzVHVwbGU+CglzdGF0aWMgYXV0byBleGVjdXRlIChjb25zdCBGdW5jdGlvblR1cGxlJiBmdW5jdGlvblR1cGxlLCBjb25zdCBBcmdzVHVwbGUmIGFyZ3NUdXBsZSkgewoJCXJldHVybiBleGVjdXRlSGVscGVyKGZ1bmN0aW9uVHVwbGUsIHN0ZDo6bWFrZV9pbmRleF9zZXF1ZW5jZTxzdGQ6OnR1cGxlX3NpemU8RnVuY3Rpb25UdXBsZT46OnZhbHVlPnt9LCBHZXRTdWJ0dXBsZTxTdW1zLCBJcz46OmdldChhcmdzVHVwbGUpLi4uKTsKCX0KcHJpdmF0ZToKCXRlbXBsYXRlIDx0eXBlbmFtZSBGdW5jdGlvblR1cGxlLCBzdGQ6OnNpemVfdC4uLiBKcywgdHlwZW5hbWUuLi4gVHVwbGVBcmdzPgoJc3RhdGljIGF1dG8gZXhlY3V0ZUhlbHBlciAoY29uc3QgRnVuY3Rpb25UdXBsZSYgZnVuY3Rpb25UdXBsZSwgY29uc3Qgc3RkOjppbmRleF9zZXF1ZW5jZTxKcy4uLj4mLCBjb25zdCBUdXBsZUFyZ3MmLi4uIHR1cGxlQXJncykgewoJCWNvbnN0IGF1dG8gdHVwbGVPZlR1cGxlcyA9IHN0ZDo6bWFrZV90dXBsZSh0dXBsZUFyZ3MuLi4pOwoJLy8JY29uc3QgaW50IGFbXSA9IHsoYXBwbHkoc3RkOjpnZXQ8SnM+KGZ1bmN0aW9uVHVwbGUpLCBzdGQ6OmdldDxKcz4odHVwbGVPZlR1cGxlcykpLCAwKS4uLn07ICAvLy8vLyBKdXN0IGEgVGVzdC4gIE9yZGVyIG9mIGZ1bmN0aW9uIGNhbGwgY29ycmVjdC4KCQlyZXR1cm4gc3RkOjptYWtlX3R1cGxlIChhcHBseShzdGQ6OmdldDxKcz4oZnVuY3Rpb25UdXBsZSksIHN0ZDo6Z2V0PEpzPih0dXBsZU9mVHVwbGVzKSkuLi4pOyAgLy8vLy8gIG9yZGVyIG9mIGZ1bmN0aW9uIGNhbGwgcmV2ZXJzZWQuICBOZWVkIHRvIGRlZmluZSBtYWtlX3R1cGxlX2xlZnRfdG9fcmlnaHQgd2hpY2ggcmV0dXJucyB0aGUgc2FtZSBhcyBtYWtlX3R1cGxlIGJ1dCBjYWxscyBmcm9tIGxlZnQgdG8gcmlnaHQuCgl9Cn07IAoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90Li4uIElzLCB0eXBlbmFtZSBBcmdzVHVwbGUsIHR5cGVuYW1lLi4uIEZzPgphdXRvIG11bHRpRnVuY3Rpb24gKGNvbnN0IEFyZ3NUdXBsZSYgYXJnc1R1cGxlLCBGcy4uLiBmcykgewoJcmV0dXJuIE11bHRpRnVuY3Rpb248dHlwZW5hbWUgUGFydGlhbFN1bXM8c3RkOjpzaXplX3QsIElzLi4uPjo6dHlwZSwgSXMuLi4+OjpleGVjdXRlIChzdGQ6Om1ha2VfdHVwbGUoZnMuLi4pLCBhcmdzVHVwbGUpOyAKfQoKLy8gVGVzdGluZwppbnQgZm9vIChpbnQsIGNoYXIpIHtzdGQ6OmNvdXQgPDwgImZvb1xuIjsgIHJldHVybiAwO30KZG91YmxlIGJhciAoYm9vbCwgZG91YmxlLCBsb25nKSB7c3RkOjpjb3V0IDw8ICJiYXJcbiI7ICByZXR1cm4gMy41O30KYm9vbCBiYXogKGNoYXIsIHNob3J0LCBmbG9hdCkge3N0ZDo6Y291dCA8PCAiYmF6XG4iOyAgcmV0dXJuIHRydWU7fQoKaW50IG1haW4oKSB7Cgljb25zdCBhdXRvIHR1cGxlID0gc3RkOjptYWtlX3R1cGxlKDUsICdhJywgdHJ1ZSwgMy41LCAxMDAwLCAndCcsIDIsIDUuOCk7Cgljb25zdCBhdXRvIHQgPSBtdWx0aUZ1bmN0aW9uPDIsMywzPiAodHVwbGUsIGZvbywgYmFyLCBiYXopOwoJc3RkOjpjb3V0IDw8IHN0ZDo6Ym9vbGFscGhhIDw8IHN0ZDo6Z2V0PDA+KHQpIDw8ICcgJyA8PCBzdGQ6OmdldDwxPih0KSA8PCAnICcgPDwgc3RkOjpnZXQ8Mj4odCkgPDwgJ1xuJzsKfQ==