Wie erweitere ich ein Tupel in die Argumente einer variadischen Vorlagenfunktion?

Lesezeit: 18 Minuten

Betrachten Sie den Fall einer Vorlagenfunktion mit variadischen Vorlagenargumenten:

template<typename Tret, typename... T> Tret func(const T&... t);

Jetzt habe ich ein Tupel t von Werten. Wie rufe ich an func() die Tupelwerte als Argumente verwenden? Ich habe über die gelesen bind() Funktionsobjekt, mit call() Funktion, und auch die apply() Funktion in verschiedenen, inzwischen veralteten Dokumenten. Die Implementierung von GNU GCC 4.4 scheint eine zu haben call() Funktion in der bind() Klasse, aber es gibt sehr wenig Dokumentation zu diesem Thema.

Einige Leute schlagen handgeschriebene rekursive Hacks vor, aber der wahre Wert von variadischen Template-Argumenten besteht darin, sie in Fällen wie oben verwenden zu können.

Hat jemand eine Lösung dafür, oder einen Hinweis, wo man darüber lesen kann?

  • Der C++14-Standard hat eine Lösung, siehe; open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html

    – Skeen

    15. Oktober 2013 um 21:34 Uhr

  • Die Idee ist, das Tupel in einer einzigen variadischen Explosion zu entpacken, indem es verwendet wird integer_sequencesehen en.cppreference.com/w/cpp/utility/integer_sequence

    – Skeen

    15. Oktober 2013 um 21:36 Uhr

  • Mit einem integer_sequence Srufen Sie Ihre Funktion einfach als auf func(std::get<S>(tuple)...)und lassen Sie den Compiler den Rest erledigen.

    – Skeen

    15. Oktober 2013 um 21:39 Uhr

  • Wenn Sie C++17 oder höher verwenden, ignorieren Sie diese Antwort und sehen Sie sich die folgende mit std::apply an

    – lewis

    30. April 2019 um 15:00 Uhr

Wie erweitere ich ein Tupel in die Argumente einer variadischen
Mohammed Alaggan

In C++17 können Sie dies tun:

std::apply(the_function, the_tuple);

Dies funktioniert bereits in Clang++ 3.9 mit std::experimental::apply.

Als Antwort auf den Kommentar, dass dies nicht funktioniert, wenn the_function Vorlage ist, ist das Folgende eine Problemumgehung:

#include <tuple>

template <typename T, typename U> void my_func(T &&t, U &&u) {}

int main(int argc, char *argv[argc]) {

  std::tuple<int, float> my_tuple;

  std::apply([](auto &&... args) { my_func(args...); }, my_tuple);

  return 0;
}

Diese Problemumgehung ist eine vereinfachte Lösung für das allgemeine Problem des Übergebens von Überladungssätzen und Funktionsvorlagen, wo eine Funktion erwartet wird. Die allgemeine Lösung (eine, die sich um Perfect-Forwarding, Constexpr-ness und Noexcept-ness kümmert) wird hier vorgestellt: https://blog.tartanllama.xyz/passing-overload-sets/.

  • Gemäß dem Beispielcode at std::anwenden es scheint nicht zu funktionieren, wenn the_function ist schablonenhaft.

    – Zitrax

    4. September 2017 um 20:45 Uhr

  • @Zitrax Sie können die Vorlagenargumente der Funktion angeben: std::apply(add_generic<float>, std::make_pair(2.0f, 3.0f));

    – Erbureth

    24. Mai 2018 um 13:29 Uhr

  • Dies ist die einfachste und eleganteste Lösung. Und es wirkt Wunder. Vielen Dank, M. Alaggan!!!!!! +100 Stimmen

    – Elliot

    22. Dezember 2019 um 9:31 Uhr

Wie erweitere ich ein Tupel in die Argumente einer variadischen
David

Hier ist mein Code, falls es jemanden interessiert

Grundsätzlich entrollt der Compiler zur Kompilierzeit alle Argumente rekursiv in verschiedenen inklusiven Funktionsaufrufen -> Aufrufe -> Aufrufe … -> Aufrufe <0>, was der letzte ist, und der Compiler optimiert weg die verschiedenen Zwischenfunktionsaufrufe, um nur den letzten zu behalten, der das Äquivalent von func(arg1, arg2, arg3, …)

Es werden 2 Versionen bereitgestellt, eine für eine Funktion, die von einem Objekt aufgerufen wird, und die andere für eine statische Funktion.

#include <tr1/tuple>

/**
 * Object Function Tuple Argument Unpacking
 *
 * This recursive template unpacks the tuple parameters into
 * variadic template arguments until we reach the count of 0 where the function
 * is called with the correct parameters
 *
 * @tparam N Number of tuple arguments to unroll
 *
 * @ingroup g_util_tuple
 */
template < uint N >
struct apply_obj_func
{
  template < typename T, typename... ArgsF, typename... ArgsT, typename... Args >
  static void applyTuple( T* pObj,
                          void (T::*f)( ArgsF... ),
                          const std::tr1::tuple<ArgsT...>& t,
                          Args... args )
  {
    apply_obj_func<N-1>::applyTuple( pObj, f, t, std::tr1::get<N-1>( t ), args... );
  }
};

//-----------------------------------------------------------------------------

/**
 * Object Function Tuple Argument Unpacking End Point
 *
 * This recursive template unpacks the tuple parameters into
 * variadic template arguments until we reach the count of 0 where the function
 * is called with the correct parameters
 *
 * @ingroup g_util_tuple
 */
template <>
struct apply_obj_func<0>
{
  template < typename T, typename... ArgsF, typename... ArgsT, typename... Args >
  static void applyTuple( T* pObj,
                          void (T::*f)( ArgsF... ),
                          const std::tr1::tuple<ArgsT...>& /* t */,
                          Args... args )
  {
    (pObj->*f)( args... );
  }
};

//-----------------------------------------------------------------------------

/**
 * Object Function Call Forwarding Using Tuple Pack Parameters
 */
// Actual apply function
template < typename T, typename... ArgsF, typename... ArgsT >
void applyTuple( T* pObj,
                 void (T::*f)( ArgsF... ),
                 std::tr1::tuple<ArgsT...> const& t )
{
   apply_obj_func<sizeof...(ArgsT)>::applyTuple( pObj, f, t );
}

//-----------------------------------------------------------------------------

/**
 * Static Function Tuple Argument Unpacking
 *
 * This recursive template unpacks the tuple parameters into
 * variadic template arguments until we reach the count of 0 where the function
 * is called with the correct parameters
 *
 * @tparam N Number of tuple arguments to unroll
 *
 * @ingroup g_util_tuple
 */
template < uint N >
struct apply_func
{
  template < typename... ArgsF, typename... ArgsT, typename... Args >
  static void applyTuple( void (*f)( ArgsF... ),
                          const std::tr1::tuple<ArgsT...>& t,
                          Args... args )
  {
    apply_func<N-1>::applyTuple( f, t, std::tr1::get<N-1>( t ), args... );
  }
};

//-----------------------------------------------------------------------------

/**
 * Static Function Tuple Argument Unpacking End Point
 *
 * This recursive template unpacks the tuple parameters into
 * variadic template arguments until we reach the count of 0 where the function
 * is called with the correct parameters
 *
 * @ingroup g_util_tuple
 */
template <>
struct apply_func<0>
{
  template < typename... ArgsF, typename... ArgsT, typename... Args >
  static void applyTuple( void (*f)( ArgsF... ),
                          const std::tr1::tuple<ArgsT...>& /* t */,
                          Args... args )
  {
    f( args... );
  }
};

//-----------------------------------------------------------------------------

/**
 * Static Function Call Forwarding Using Tuple Pack Parameters
 */
// Actual apply function
template < typename... ArgsF, typename... ArgsT >
void applyTuple( void (*f)(ArgsF...),
                 std::tr1::tuple<ArgsT...> const& t )
{
   apply_func<sizeof...(ArgsT)>::applyTuple( f, t );
}

// ***************************************
// Usage
// ***************************************

template < typename T, typename... Args >
class Message : public IMessage
{

  typedef void (T::*F)( Args... args );

public:

  Message( const std::string& name,
           T& obj,
           F pFunc,
           Args... args );

private:

  virtual void doDispatch( );

  T*  pObj_;
  F   pFunc_;
  std::tr1::tuple<Args...> args_;
};

//-----------------------------------------------------------------------------

template < typename T, typename... Args >
Message<T, Args...>::Message( const std::string& name,
                              T& obj,
                              F pFunc,
                              Args... args )
: IMessage( name ),
  pObj_( &obj ),
  pFunc_( pFunc ),
  args_( std::forward<Args>(args)... )
{

}

//-----------------------------------------------------------------------------

template < typename T, typename... Args >
void Message<T, Args...>::doDispatch( )
{
  try
  {
    applyTuple( pObj_, pFunc_, args_ );
  }
  catch ( std::exception& e )
  {

  }
}

  • Ist es möglich, dies so anzupassen, dass es in einem Fall funktioniert, in dem die betreffende “Funktion” tatsächlich ein Konstruktor ist?

    – Oberbefehlshaber4

    6. September 2010 um 21:46 Uhr

  • Könnten Sie ein Beispiel dafür geben, was Sie tun möchten, und wir können von dort aus weitermachen.

    – David

    7. September 2010 um 10:25 Uhr


  • Diese Lösung bietet nur einen Overhead für die Kompilierzeit und wird am Ende vereinfacht zu (pObj->*f)( arg0, arg,1, … argN); rechts?

    – Doof

    5. November 2010 um 0:17 Uhr


  • Ja, der Compiler komprimiert die mehrfachen Funktionsaufrufe in den letzten, als ob Sie ihn selbst geschrieben hätten, was das Schöne an all diesem Meta-Programmierkram ist.

    – David

    5. November 2010 um 12:48 Uhr

  • all die tr1 Sachen können jetzt mit c++11 herausgenommen werden

    – Ryan Haining

    12. September 2013 um 4:58 Uhr

1647095412 412 Wie erweitere ich ein Tupel in die Argumente einer variadischen
sigidagi

In C++ gibt es viele Möglichkeiten, Tupel zu erweitern/entpacken und diese Tupelelemente auf eine variadische Vorlagenfunktion anzuwenden. Hier ist eine kleine Hilfsklasse, die ein Indexarray erstellt. Es wird häufig in der Template-Metaprogrammierung verwendet:

// ------------- 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...> 
{}; 

Jetzt ist der Code, der die Arbeit erledigt, nicht so groß:

 // ----------UNPACK TUPLE AND APPLY TO FUNCTION ---------
#include <tuple>
#include <iostream> 

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

Der Test ist unten dargestellt:

// --------------------- TEST ------------------
void one(int i, double d)
{
    std::cout << "function one(" << i << ", " << d << ");\n";
}
int two(int i)
{
    std::cout << "function two(" << i << ");\n";
    return i;
}

int main()
{
    std::tuple<int, double> tup(23, 4.5);
    apply(one, tup);

    int d = apply(two, std::make_tuple(2));    

    return 0;
}

Ich bin kein großer Experte für andere Sprachen, aber ich denke, wenn diese Sprachen keine solche Funktionalität in ihrem Menü haben, gibt es keine Möglichkeit, dies zu tun. Zumindest mit C++ können Sie das, und ich denke, es ist nicht so kompliziert …

  • “… und diese Tupelelemente auf eine variadische Vorlagenfunktion anwenden”. Der Testabschnitt enthält jedoch nur Nicht-Template-Variadic-Funktionen. Wenn ich ein Like hinzufüge template<class ... T> void three(T...) {} und versuchen Sie, apply darauf zu verwenden, dass es nicht kompiliert wird.

    – Zitrax

    4. September 2017 um 21:41 Uhr

  • Leider funktioniert diese Technik nicht in nvcc (und wahrscheinlich anderen EDG-basierten Compilern). Es scheitert mit error: template parameter pack not at end of parameter listin der Schlange template<class Ret, class... Args, int... Indexes > Ret apply_helper( Ret (*pf)(Args...), index_tuple< Indexes... >, tuple<Args...>&& tup) .

    – alfC

    21. Dezember 2020 um 12:30 Uhr

Das finde ich die eleganteste Lösung (und wird optimal weitergeleitet):

#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>

template<size_t N>
struct Apply {
    template<typename F, typename T, typename... A>
    static inline auto apply(F && f, T && t, A &&... a)
        -> decltype(Apply<N-1>::apply(
            ::std::forward<F>(f), ::std::forward<T>
            ::std::get<N-1>(::std::forward<T>
        ))
    {
        return Apply<N-1>::apply(::std::forward<F>(f), ::std::forward<T>
            ::std::get<N-1>(::std::forward<T>
        );
    }
};

template<>
struct Apply<0> {
    template<typename F, typename T, typename... A>
    static inline auto apply(F && f, T &&, A &&... a)
        -> decltype(::std::forward<F>(f)(::std::forward<A>(a)...))
    {
        return ::std::forward<F>(f)(::std::forward<A>(a)...);
    }
};

template<typename F, typename T>
inline auto apply(F && f, T && t)
    -> decltype(Apply< ::std::tuple_size<
        typename ::std::decay<T>::type
    >::value>::apply(::std::forward<F>(f), ::std::forward<T>
{
    return Apply< ::std::tuple_size<
        typename ::std::decay<T>::type
    >::value>::apply(::std::forward<F>(f), ::std::forward<T>
}

Beispielnutzung:

void foo(int i, bool b);

std::tuple<int, bool> t = make_tuple(20, false);

void m()
{
    apply(&foo, t);
}

Leider kann GCC (mindestens 4.6) dies nicht mit “Entschuldigung, nicht implementiert: Mangelüberladung” kompilieren (was einfach bedeutet, dass der Compiler die C++ 11-Spezifikation noch nicht vollständig implementiert), und da er verschiedene Vorlagen verwendet, wird er dies nicht tun Arbeit in MSVC, also ist es mehr oder weniger nutzlos. Sobald es jedoch einen Compiler gibt, der die Spezifikation unterstützt, ist dies IMHO der beste Ansatz. (Hinweis: Es ist nicht so schwer, dies so zu ändern, dass Sie die Mängel in GCC umgehen oder mit Boost Preprocessor implementieren können, aber es ruiniert die Eleganz, also poste ich diese Version.)

GCC 4.7 unterstützt diesen Code jetzt problemlos.

Bearbeiten: Um den eigentlichen Funktionsaufruf herum hinzugefügt, um das Rvalue-Referenzformular zu unterstützen * dies, falls Sie Clang verwenden (oder wenn jemand anderes tatsächlich dazu kommt, es hinzuzufügen).

Bearbeiten: Fehlendes Vorwärts um das Funktionsobjekt im Körper der Nicht-Member-Apply-Funktion hinzugefügt. Danke an pheedbaq für den Hinweis, dass es fehlte.

Bearbeiten: Und hier ist die C ++ 14-Version, nur weil sie so viel schöner ist (noch nicht wirklich kompiliert):

#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>

template<size_t N>
struct Apply {
    template<typename F, typename T, typename... A>
    static inline auto apply(F && f, T && t, A &&... a) {
        return Apply<N-1>::apply(::std::forward<F>(f), ::std::forward<T>
            ::std::get<N-1>(::std::forward<T>
        );
    }
};

template<>
struct Apply<0> {
    template<typename F, typename T, typename... A>
    static inline auto apply(F && f, T &&, A &&... a) {
        return ::std::forward<F>(f)(::std::forward<A>(a)...);
    }
};

template<typename F, typename T>
inline auto apply(F && f, T && t) {
    return Apply< ::std::tuple_size< ::std::decay_t<T>
      >::value>::apply(::std::forward<F>(f), ::std::forward<T>
}

Hier ist eine Version für Member-Funktionen (nicht sehr viel getestet!):

using std::forward; // You can change this if you like unreadable code or care hugely about namespace pollution.

template<size_t N>
struct ApplyMember
{
    template<typename C, typename F, typename T, typename... A>
    static inline auto apply(C&& c, F&& f, T&& t, A&&... a) ->
        decltype(ApplyMember<N-1>::apply(forward<C>(c), forward<F>(f), forward<T>
    {
        return ApplyMember<N-1>::apply(forward<C>(c), forward<F>(f), forward<T>
    }
};

template<>
struct ApplyMember<0>
{
    template<typename C, typename F, typename T, typename... A>
    static inline auto apply(C&& c, F&& f, T&&, A&&... a) ->
        decltype((forward<C>(c)->*forward<F>(f))(forward<A>(a)...))
    {
        return (forward<C>(c)->*forward<F>(f))(forward<A>(a)...);
    }
};

// C is the class, F is the member function, T is the tuple.
template<typename C, typename F, typename T>
inline auto apply(C&& c, F&& f, T&& t) ->
    decltype(ApplyMember<std::tuple_size<typename std::decay<T>::type>::value>::apply(forward<C>(c), forward<F>(f), forward<T>
{
    return ApplyMember<std::tuple_size<typename std::decay<T>::type>::value>::apply(forward<C>(c), forward<F>(f), forward<T>
}
// Example:

class MyClass
{
public:
    void foo(int i, bool b);
};

MyClass mc;

std::tuple<int, bool> t = make_tuple(20, false);

void m()
{
    apply(&mc, &MyClass::foo, t);
}

1647095412 158 Wie erweitere ich ein Tupel in die Argumente einer variadischen
Peter Som

template<typename F, typename Tuple, std::size_t ... I>
auto apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>) {
    return std::forward<F>(f)(std::get<I>(std::forward<Tuple>
}
template<typename F, typename Tuple>
auto apply(F&& f, Tuple&& t) {
    using Indices = std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>;
    return apply_impl(std::forward<F>(f), std::forward<Tuple>
}

Dies wird mithilfe von index_sequence aus dem C++14-Entwurf übernommen. Ich könnte vorschlagen, sie in einem zukünftigen Standard (TS) anwenden zu lassen.

1647095413 999 Wie erweitere ich ein Tupel in die Argumente einer variadischen
Gemeinschaft

All diese Implementierungen sind gut. Aber aufgrund der Verwendung eines Zeigers auf den Member-Funktions-Compiler kann der Zielfunktionsaufruf oft nicht inline sein (zumindest kann gcc 4.8 das nicht, egal was, warum gcc keine Funktionszeiger inline kann, die bestimmt werden können?)

Aber die Dinge ändern sich, wenn der Zeiger an die Member-Funktion als Template-Argumente gesendet wird, nicht als Funktionsparameter:

/// from https://stackoverflow.com/a/9288547/1559666
template<int ...> struct seq {};
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};
template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };

template<typename TT>
using makeSeq = typename gens< std::tuple_size< typename std::decay<TT>::type >::value >::type;


// deduce function return type
template<class ...Args>
struct fn_type;

template<class ...Args>
struct fn_type< std::tuple<Args...> >{

    // will not be called
    template<class Self, class Fn>
    static auto type_helper(Self &self, Fn f) -> decltype((self.*f)(declval<Args>()...)){
        //return (self.*f)(Args()...);
        return NULL;
    }
};

template<class Self, class ...Args>
struct APPLY_TUPLE{};

template<class Self, class ...Args>
struct APPLY_TUPLE<Self, std::tuple<Args...>>{
    Self &self;
    APPLY_TUPLE(Self &self): self(self){}

    template<class T, T (Self::* f)(Args...),  class Tuple>
    void delayed_call(Tuple &&list){
        caller<T, f, Tuple >(forward<Tuple>(list), makeSeq<Tuple>() );
    }

    template<class T, T (Self::* f)(Args...), class Tuple, int ...S>
    void caller(Tuple &&list, const seq<S...>){
        (self.*f)( std::get<S>(forward<Tuple>(list))... );
    }
};

#define type_of(val) typename decay<decltype(val)>::type

#define apply_tuple(obj, fname, tuple) \
    APPLY_TUPLE<typename decay<decltype(obj)>::type, typename decay<decltype(tuple)>::type >(obj).delayed_call< \
            decltype( fn_type< type_of(tuple) >::type_helper(obj, &decay<decltype(obj)>::type::fname) ), \
            &decay<decltype(obj)>::type::fname \
            > \
            (tuple);

Und Verwendung:

struct DelayedCall
{  
    void call_me(int a, int b, int c){
        std::cout << a+b+c;
    }

    void fire(){
        tuple<int,int,int> list = make_tuple(1,2,3);
        apply_tuple(*this, call_me, list); // even simpler than previous implementations
    }
};

Beweis für Inlinable http://goo.gl/5UqVnC


Mit kleinen Änderungen können wir „überladen“ apply_tuple:

#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(X,##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
#define VARARG_IMPL_(base, count, ...) base##count(__VA_ARGS__)
#define VARARG_IMPL(base, count, ...) VARARG_IMPL_(base, count, __VA_ARGS__)
#define VARARG(base, ...) VARARG_IMPL(base, VA_NARGS(__VA_ARGS__), __VA_ARGS__)

#define apply_tuple2(fname, tuple) apply_tuple3(*this, fname, tuple)
#define apply_tuple3(obj, fname, tuple) \
    APPLY_TUPLE<typename decay<decltype(obj)>::type, typename decay<decltype(tuple)>::type >(obj).delayed_call< \
            decltype( fn_type< type_of(tuple) >::type_helper(obj, &decay<decltype(obj)>::type::fname) ), \
            &decay<decltype(obj)>::type::fname \
            /* ,decltype(tuple) */> \
            (tuple);
#define apply_tuple(...) VARARG(apply_tuple, __VA_ARGS__)

...

apply_tuple(obj, call_me, list);
apply_tuple(call_me, list);       // call this->call_me(list....)

Außerdem ist dies die einzige Lösung, die mit Vorlagenfunktionen arbeitet.

1) Wenn Sie eine fertige parameter_pack-Struktur als Funktionsargument haben, können Sie std::tie einfach so verwenden:

template <class... Args>
void tie_func(std::tuple<Args...> t, Args&... args)
{
 std::tie<Args...>(args...) = t;
}

int main()
{
 std::tuple<int, double, std::string> t(2, 3.3, "abc");

 int i;
 double d;
 std::string s;

 tie_func(t, i, d, s);

 std::cout << i << " " << d << " " << s << std::endl;
}

2) Wenn Sie kein fertiges Parampack arg haben, müssen Sie das Tupel wie folgt abwickeln

#include <tuple>
#include <functional>
#include <iostream>



template<int N>
struct apply_wrap {
    template<typename R, typename... TupleArgs, typename... UnpackedArgs>
    static R applyTuple( std::function<R(TupleArgs...)>& f, const std::tuple<TupleArgs...>& t, UnpackedArgs... args )
    {
        return apply_wrap<N-1>::applyTuple( f, t, std::get<N-1>( t ), args... );
    }
};


template<>
struct apply_wrap<0>
{
    template<typename R, typename... TupleArgs, typename... UnpackedArgs>
    static R applyTuple( std::function<R(TupleArgs...)>& f, const std::tuple<TupleArgs...>&, UnpackedArgs... args )
    {
        return f( args... );
    }
};



template<typename R, typename... TupleArgs>
R applyTuple( std::function<R(TupleArgs...)>& f, std::tuple<TupleArgs...> const& t )
{
    return apply_wrap<sizeof...(TupleArgs)>::applyTuple( f, t );
}



int fac(int n)
{
    int r=1;
    for(int i=2; i<=n; ++i)
        r *= i;
    return r;
}



int main()
{
    auto t = std::make_tuple(5);
    auto f = std::function<decltype(fac)>(&fac);
    cout << applyTuple(f, t);
}

993970cookie-checkWie erweitere ich ein Tupel in die Argumente einer variadischen Vorlagenfunktion?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy