আমি কীভাবে বৈচিত্রিক টেম্পলেট ফাংশনের যুক্তিতে একটি টুপল প্রসারিত করব?


135

ভের্যাডিক টেম্পলেট আর্গুমেন্টগুলির সাথে একটি টেম্প্লেটেড ফাংশনের ক্ষেত্রে বিবেচনা করুন:

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

এখন, আমি tমান একটি দ্বিগুণ আছে । আমি কীভাবে func()টিপল মানগুলি আর্গুমেন্ট হিসাবে ব্যবহার করব ? আমি পড়েছি bind()ফাংশন বস্তু, সঙ্গে call()ফাংশন, এবং এছাড়াও apply()বিভিন্ন কিছু এখন অপ্রচলিত দস্তাবেজে ফাংশন। জিএনইউ জিসিসি ৪.৪ বাস্তবায়নের ক্লাসে কোনও call()কার্যকারিতা রয়েছে বলে মনে হচ্ছে bind()তবে বিষয়টিতে খুব কম ডকুমেন্টেশন রয়েছে।

কিছু লোক হস্ত-লিখিত পুনরাবৃত্তির হ্যাকগুলির পরামর্শ দেয় তবে ভ্যারিয়্যাডিক টেম্পলেট আর্গুমেন্টগুলির আসল মান হ'ল উপরের মতো ক্ষেত্রে এগুলি ব্যবহার করতে সক্ষম হওয়া।

কারও কাছেই এর সমাধান আছে, বা কোথায় পড়তে হবে তার ইঙ্গিত রয়েছে?


5
সি ++ 14 মানের একটি সমাধান দেখুন; open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
Skeen

1
ধারণা একটি একক variadic বিস্ফোরণে tuple প্যাকমুক্ত ব্যবহার হয় integer_sequence, দেখুন en.cppreference.com/w/cpp/utility/integer_sequence
Skeen

6
একটি থাকার পরে integer_sequence S, আপনি কেবল আপনার ফাংশনটিকে এটি হিসাবে কল করুন func(std::get<S>(tuple)...)এবং সংকলকটিকে বাকীটি পরিচালনা করতে দিন।
স্কেইন

1
যদি C ++ 17 বা তার বেশি ব্যবহার করে থাকেন তবে এই উত্তরটি উপেক্ষা করুন এবং নীচের উত্তরটি std :: ব্যবহার করে দেখুন
লুইস

উত্তর:


46

যদি কেউ আগ্রহী হয় তবে আমার কোডটি এখানে

মূলত সংকলনের সময়ে সংকলকটি বিভিন্ন অন্তর্ভুক্ত ফাংশন কলগুলিতে <<> -> কল <N-1> -> কলগুলি ... -> কলস <0> পুনরাবৃত্তভাবে সমস্ত যুক্তি তালিকাভুক্ত করবে যা শেষটি এবং সংকলকটি অপ্টিমাইজ করবে বিভিন্ন মধ্যবর্তী ফাংশন কেবল শেষটিকে রাখার জন্য কল করে যা ফানকের সমতুল্য (আর্গ 1, আরগ 2, আরজি 3, ...)

2 টি সংস্করণ সরবরাহ করা আছে, একটিতে কোনও বস্তুতে ডাকা একটি ফাংশন এবং অন্যটি স্ট্যাটিক ফাংশনের জন্য।

#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 )
  {

  }
}

2
প্রশ্নে "ফাংশন" আসলে একজন নির্মাতা এমন ক্ষেত্রে এটির সাথে কাজ করার জন্য কি এটি খাপ খাইয়ে নেওয়া সম্ভব?
হাইকম্যান্ডার

আপনি কী করতে চান তার একটি উদাহরণ দিতে পারেন এবং আমরা সেখান থেকে যেতে পারি।
ডেভিড

এই সমাধানটি কেবল একটি সংকলনের সময় ওভারহেড সরবরাহ করে এবং শেষে এটি সরল করা হবে (pObj -> * চ) (আরজি 0, আরগ, 1, ... আরজিএন); ঠিক আছে?
বোকা

হ্যাঁ, সংকলকটি একাধিক ফাংশন কলকে চূড়ান্তভাবে সংকুচিত করবে যেমন আপনি নিজেরাই লিখেছেন যা এই সমস্ত মেটা প্রোগ্রামিং সামগ্রীর সৌন্দর্য of
ডেভিড


37

সি ++ 17 এ আপনি এটি করতে পারেন:

std::apply(the_function, the_tuple);

এটি ইতিমধ্যে স্ট্যান্ড :: পরীক্ষামূলক :: প্রয়োগ ব্যবহার করে কলম্ব ++ 3.9 এ কাজ করে।

মন্তব্যটির জবাবে এই বলেছিলেন যে প্রলুব্ধ করা হলে the_functionএটি কাজ করবে না , নিম্নলিখিতটি একটি কাজের আশেপাশে রয়েছে:

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

এই কাজটি প্রায়শই ওভারলোড সেট এবং ফাংশন টেমপ্লেট যেখানে কোনও ফাংশন প্রত্যাশিত হবে তা পাস করার সাধারণ সমস্যার সহজ সমাধান solution সাধারণ সমাধান (এক যে নিখুঁত-ফরওয়ার্ডিং, কনটেক্সারপ্রস-নেস এবং নেক্সটস-নেস-এর যত্ন নিচ্ছে) এখানে উপস্থাপন করা হয়েছে: https://blog.tartanllama.xyz/passing-overload-sets/


স্ট্যান্ডার্ড :: উদাহরণ কোড অনুসারে প্রয়োগ করুন এটি the_functionটেম্পলেট থাকলে কাজ করে না বলে মনে হয় ।
Zitrax

1
@ জিত্রাটক্স আপনি ফাংশনের টেম্পলেট যুক্তিগুলি নির্দিষ্ট করতে পারবেন:std::apply(add_generic<float>, std::make_pair(2.0f, 3.0f));
এরবুর্থ বলেছেন মোনিকা পুনরায় ইনস্টল করুন

এটি সহজতম, সবচেয়ে মার্জিত সমাধান। এবং এটি আশ্চর্য কাজ করে। অনেক অনেক ধন্যবাদ, এম আলাগান !!!!!! +100 ভোট
এলিয়ট

36

সি ++ তে টিউপলকে প্রসারিত / আনপ্যাকিং করার অনেকগুলি উপায় রয়েছে এবং এই টিপল উপাদানগুলিকে বৈচিত্র্যযুক্ত টেম্পলেট ফাংশনে প্রয়োগ করা হয়। এখানে একটি ছোট সহায়ক শ্রেণি যা সূচক অ্যারে তৈরি করে। এটি টেমপ্লেট রূপকগুলিতে প্রচুর ব্যবহৃত হয়:

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

পরীক্ষাটি নম্রভাবে দেখানো হয়:

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

আমি অন্যান্য ভাষার ক্ষেত্রে বড় বিশেষজ্ঞ নই, তবে আমি অনুমান করি যে যদি এই ভাষাগুলির মেনুতে এই জাতীয় কার্যকারিতা না থাকে তবে এটি করার কোনও উপায় নেই। কমপক্ষে সি ++ দিয়ে আপনি পারবেন, এবং আমি মনে করি এটি এতটা জটিল নয় ...


"... এবং এই দ্বৈত উপাদানগুলিকে একটি ভেরিয়াদিক টেম্পলেট ফাংশনে প্রয়োগ করুন" । পরীক্ষার বিভাগে কেবলমাত্র টেমপ্লেট ভের্যাডিক ফাংশন রয়েছে। আমি যদি এর মতো একটি যোগ করি template<class ... T> void three(T...) {}এবং এটি প্রয়োগ করার চেষ্টা করি তবে এটি সংকলন করে না।
Zitrax

32

আমি এটি সবচেয়ে মার্জিত সমাধান বলে মনে করি (এবং এটি সর্বোত্তমভাবে এগিয়ে দেওয়া হয়েছে):

#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>(t),
            ::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
        ))
    {
        return Apply<N-1>::apply(::std::forward<F>(f), ::std::forward<T>(t),
            ::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
        );
    }
};

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>(t)))
{
    return Apply< ::std::tuple_size<
        typename ::std::decay<T>::type
    >::value>::apply(::std::forward<F>(f), ::std::forward<T>(t));
}

ব্যবহারের উদাহরণ:

void foo(int i, bool b);

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

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

দুর্ভাগ্যক্রমে জিসিসি (কমপক্ষে 6.6) "দুঃখিত, অবিহিত: ম্যাংলিং ওভারলোড" (এর সহজ অর্থ যে সংকলকটি এখনও পুরোপুরি সি ++ 11 স্পেসটি কার্যকরভাবে প্রয়োগ করে না), এবং যেহেতু এটি বৈকল্পিক টেম্পলেটগুলি ব্যবহার করে, এটি অভ্যাস করবে না এমএসভিসিতে কাজ করুন, সুতরাং এটি কম-বেশি অকেজো। যাইহোক, একবার স্পষ্ট সমর্থন করে এমন একটি সংকলক উপস্থিত থাকলে এটি সেরা পদ্ধতির আইএমএইচও হবে। (দ্রষ্টব্য: এটির সংশোধন করা এতটা কঠিন নয় যাতে আপনি জিসিসিতে ঘাটতিগুলি সমাধান করতে পারেন, বা এটি বুস্ট প্রিপ্রসেসর দিয়ে প্রয়োগ করতে পারেন, তবে এটি কমনীয়তা নষ্ট করে দেয়, তাই এটি আমি পোস্ট করছি এমন সংস্করণ))

জিসিসি 4.7 এখন এই কোডটি ঠিকঠাক সমর্থন করে।

সম্পাদনা করুন: যথাযথ রেফারেন্স ফর্মটি সমর্থন করার জন্য প্রকৃত ফাংশন কলের চারপাশে এগিয়ে যুক্ত করা হয়েছে * এটি আপনি যদি ঝাঁকুনি ব্যবহার করছেন (বা অন্য কেউ যদি বাস্তবে এটি যোগ করার আশেপাশে থাকে)।

সম্পাদনা: অ-সদস্য প্রয়োগ ফাংশনটির শরীরে ফাংশন অবজেক্টের আশেপাশে নিখোঁজ যুক্ত করা হয়েছে। অনুপস্থিত যে এটি অনুপস্থিত ছিল তা দেখানোর জন্য ফিডবাককে ধন্যবাদ।

সম্পাদনা করুন: এবং এখানে C ++ 14 সংস্করণটি কেবলমাত্র খুব সুন্দর হওয়ার কারণে (আসলে এখনও সংকলন করে না):

#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>(t),
            ::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
        );
    }
};

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

এখানে সদস্য ফাংশনগুলির জন্য একটি সংস্করণ রয়েছে (খুব বেশি পরীক্ষিত নয়!):

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>(t), std::get<N-1>(forward<T>(t)), forward<A>(a)...))
    {
        return ApplyMember<N-1>::apply(forward<C>(c), forward<F>(f), forward<T>(t), std::get<N-1>(forward<T>(t)), forward<A>(a)...);
    }
};

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>(t)))
{
    return ApplyMember<std::tuple_size<typename std::decay<T>::type>::value>::apply(forward<C>(c), forward<F>(f), forward<T>(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);
}

1
তালিকাভুক্ত উত্তরগুলির মধ্যে +1, আপনার যুক্তিগুলির সাথে কাজ করতে আমি সবচেয়ে কাছের ছিলাম যার যুক্তিগুলি ভেক্টর ... ... তবে আমি এখনও সংকলন ত্রুটি পাচ্ছি। ideone.com/xH5kBH আপনি যদি এটি -DDIRECT_CALL দিয়ে সংকলন করেন এবং চালনা করেন তবে আউটপুটটি কেমন হবে তা আপনি দেখতে পাবেন। আমি অন্যথায় একটি সংকলন ত্রুটি পেয়েছি (আমি মনে করি ডেস্কটাইপটি আমার বিশেষ কেসটি বের করার জন্য যথেষ্ট স্মার্ট নয়), সাথে জিসিসি ৪..2.২।
kfmfe04

3
আইডিয়নে জিসিসির সংস্করণটি এটি পাস করার জন্য পুরানো, এটি ম্যাংলেড ডিক্লাইপ রিটার্ন টাইপ ওভারলোডিং সমর্থন করে না। আমি এই কোডটি জিসিসি ৪.7.২ এ তুলনামূলকভাবে ভালভাবে পরীক্ষা করেছি এবং আমি কোনও সমস্যায় পড়ি না। জিসিসি ৪.৮ সহ, সমস্ত ন্যক্কারজনক ডিক্লাইপ ট্রেলিং রিটার্নের ধরণগুলি এড়াতে আপনি নতুন সি ++ 17 স্বয়ংক্রিয় রিটার্ন মান বৈশিষ্ট্যটি ব্যবহার করতে পারেন।
DRayX

1
কৌতূহলের বাইরে, সদস্যহীন applyফাংশনে, রিটার্নের টাইপের মতো কেন fকোনও std::forwardকল দিয়ে মোড়ানো হয় না ? এটির কি দরকার নেই?
ব্রেট রসিয়ার

3
কৌতূহলের বাইরে, আমি এটি জিসিসি ৪.৮ এ সংকলন করার চেষ্টা করেছি এবং -O0 ব্যতীত যে কোনও স্তরের অপ্টিমাইজেশনের সাথে foo('x', true)একই একই সমাবেশ কোডটি সংকলিত apply(foo, ::std::make_tuple('x', true))করেছি।
DRayX

2
সি ++ দিয়ে integer_sequenceআপনি এমনকি apply()এর উদাহরণটিতে প্রায় সঠিক বাস্তবায়ন পেতে পারেন । নীচে আমার উত্তর দেখুন।
পিটারসম সোম

28
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>(t))...);
}
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>(t), Indices());
}

এটি সূচক_সিকোয়েন্স ব্যবহার করে সি ++ 14 খসড়া থেকে অভিযোজিত। আমি ভবিষ্যতের স্ট্যান্ডার্ড (টিএস) এ প্রয়োগ করার প্রস্তাব দিতে পারি।


1

খবরটা ভাল লাগছে না।

সবেমাত্র প্রকাশিত খসড়া মানদণ্ডটি পড়ার পরে , আমি এর কোনও অন্তর্নির্মিত সমাধান দেখছি না, যা দেখতে অদ্ভুত বলে মনে হচ্ছে।

এই জাতীয় বিষয়গুলির সম্পর্কে জিজ্ঞাসা করার জন্য সেরা জায়গাটি (যদি আপনি ইতিমধ্যে না থাকেন) হ'ল কম্পায়াং.এল.সি.সি.আর.কে পরিমিত করা, কারণ কিছু লোকেরা নিয়মিত সেখানে স্ট্যান্ডার্ড পোস্টের খসড়া তৈরির সাথে জড়িত।

আপনি যদি এই থ্রেডটি পরীক্ষা করে দেখেন তবে কারও কাছে একই প্রশ্ন রয়েছে (সম্ভবত এটি আপনি, এক্ষেত্রে আপনি এই পুরো উত্তরটি খানিকটা হতাশাই খুঁজে পেতে চলেছেন!) এবং কয়েকটি বাট-কুরুচিপূর্ণ প্রয়োগের পরামর্শ দেওয়া হচ্ছে।

আমি কেবল ভাবলাম tupleযে রূপান্তরটি সহজতর হিসাবে ফাংশনটি গ্রহণযোগ্যতর করা সহজ কি না be তবে এর থেকে বোঝা যায় যে সমস্ত ফাংশনকে সর্বোচ্চ নমনীয়তার জন্য টিপলসকে আর্গুমেন্ট হিসাবে গ্রহণ করা উচিত, এবং যাতে কেবল টিপলটি আর্গুমেন্ট প্যাকের বিল্ট-ইন প্রসারণ না দেওয়ার অদ্ভুততা প্রদর্শন করে।

আপডেট: উপরের লিঙ্কটি কাজ করে না - এটি আটকানোর চেষ্টা করুন:

http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/750fa3815cdaac45/d8dc09e34bbb9661?lnk=gst&q=tuple+variadic#d8dc09e34bbb9661


আমি ভাবছি কেন তারা এমনকি টিউপল এবং ফাংশন আর্গুমেন্ট প্যাকের পৃথক ধারণা থাকতে বিরক্ত করে। সম্ভবত একটি সংমিশ্রণকারী সংকলকটিতে তারা বিনিময়যোগ্য তবে আমি তাদের সম্পর্কে যে কোনও জায়গায় পড়েছি তার কোনও ইঙ্গিত আমি খুঁজে পাইনি।
ড্যানিয়েল আর্উইকার

2
কারণ টিপল <ইন, চর, স্ট্রিং> পৃথক প্রকার হিসাবে প্রয়োজনীয়; যেমন কোনও ফাংশন তৈরির ক্ষমতা যা প্রতিটি কলের মাঝখানে মেক_ টাইপের প্রয়োজন হয় না।
কোপপ্রো

1
এছাড়াও, সেরা স্থানটি কম.কম। C ++ 1x সম্পর্কিত প্রশ্নগুলি প্রায় সবসময় কম.স্টিডি। সি ++ এর জন্য আরও ভালভাবে পরিচালিত হয়।
কোপপ্রো

1

এই সমস্ত বাস্তবায়ন ভাল। তবে সদস্য ফাংশন সংকলকের পয়েন্টার ব্যবহারের কারণে প্রায়শই লক্ষ্য ফাংশন কলটি ইনলাইন করতে পারে না (কমপক্ষে জিসিসি ৪.৮ পারে না, কেন জিসিসি ফাংশন পয়েন্টারগুলিকে ইনলাইন করতে পারে না তা নির্ধারণ করা যায় না কেন? )

ফাংশন প্যারাম হিসাবে নয়, টেমপ্লেট আর্গুমেন্ট হিসাবে সদস্য ফাংশনে পয়েন্টার পাঠালে জিনিস পরিবর্তন হয়:

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

এবং ব্যবহার:

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

অন্তর্নিহিত http://goo.gl/5UqVnC এর প্রমাণ


ছোট পরিবর্তন সহ, আমরা "ওভারলোড" করতে পারি 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....)

প্লাস এটিই একমাত্র সমাধান যা টেম্পলেটড ফাংশনগুলির সাথে কাজ করে।


1

1) যদি আপনার ফাংশন আর্গুমেন্ট হিসাবে একটি প্যারামিটার_প্যাক কাঠামো কাঠামো থাকে তবে আপনি কেবল এসটিডি :: টাই ব্যবহার করতে পারেন:

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) যদি আপনার কাছে তৈরি প্যারাম্প্যাক আরগ না থাকে তবে আপনাকে এই ধরণের টিপলটি খুলে ফেলতে হবে

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

0

এটি সম্পর্কে:

// Warning: NOT tested!
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>

using std::declval;
using std::forward;
using std::get;
using std::integral_constant;
using std::size_t;
using std::tuple;

namespace detail
{
    template < typename Func, typename ...T, typename ...Args >
    auto  explode_tuple( integral_constant<size_t, 0u>, tuple<T...> const &t,
     Func &&f, Args &&...a )
     -> decltype( forward<Func>(f)(declval<T const>()...) )
    { return forward<Func>( f )( forward<Args>(a)... ); }

    template < size_t Index, typename Func, typename ...T, typename ...Args >
    auto  explode_tuple( integral_constant<size_t, Index>, tuple<T...> const&t,
     Func &&f, Args &&...a )
     -> decltype( forward<Func>(f)(declval<T const>()...) )
    {
        return explode_tuple( integral_constant<size_t, Index - 1u>{}, t,
         forward<Func>(f), get<Index - 1u>(t), forward<Args>(a)... );
    }
}

template < typename Func, typename ...T >
auto  run_tuple( Func &&f, tuple<T...> const &t )
 -> decltype( forward<Func>(f)(declval<T const>()...) )
{
    return detail::explode_tuple( integral_constant<size_t, sizeof...(T)>{}, t,
     forward<Func>(f) );
}

template < typename Tret, typename ...T >
Tret  func_T( tuple<T...> const &t )
{ return run_tuple( &func<Tret, T...>, t ); }

run_tupleফাংশন টেমপ্লেট দেওয়া tuple নেয় এবং প্রদত্ত ফাংশন পৃথকভাবে তার উপাদান পাস। এটি পুনরুক্তরূপে তার সহায়ক ফাংশন টেমপ্লেটগুলি কল করে এটির কাজ চালায় explode_tuple। এটি গুরুত্বপূর্ণ যে run_tupleটিপলের আকারটি এতে পাস করে explode_tuple; সেই সংখ্যাটি কতগুলি উপাদান নিষ্কাশন করতে পারে তার একটি কাউন্টার হিসাবে কাজ করে।

যদি টিপলটি খালি থাকে তবে দূরবর্তী ফাংশনটির সাথে run_tupleপ্রথম সংস্করণটিকে explode_tupleকেবলমাত্র অন্য যুক্তি হিসাবে কল করে । রিমোট ফাংশনটি কোনও যুক্তি ছাড়াই ডাকা হয় এবং আমরা সম্পন্ন করেছি। যদি টিপলটি খালি না explode_tupleথাকে তবে দূরবর্তী ফাংশন সহ একটি উচ্চতর সংখ্যার দ্বিতীয় সংস্করণে পাঠানো হয় । একটি পুনরাবৃত্তি কলexplode_tupleএকই আর্গুমেন্টের সাহায্যে তৈরি করা হয়, ব্যতীত কাউন্টার সংখ্যাটি এক দ্বারা হ্রাস পায় এবং (একটি রেফারেন্স) শেষ টিপল উপাদানটি দূরবর্তী ফাংশনের পরে আর্গুমেন্ট হিসাবে সজ্জিত করা হয়। একটি পুনরাবৃত্তির কলে, কাউন্টারটি শূন্য নয়, এবং কাউন্টারটির সাথে আবার একটি কল করা হয়েছিল আবার হ্রাস পেয়েছে এবং পরবর্তী-অপ্রয়োজনীয় উপাদানটি রিমোট ফাংশনের পরে আর্গুমেন্ট তালিকায় সন্নিবেশ করা হয়েছে তবে অন্যান্য sertedোকানো আর্গুমেন্টের আগে, বা কাউন্টারে পৌঁছায় শূন্য এবং রিমোট ফাংশনটি তার পরে জমে থাকা সমস্ত আর্গুমেন্টের সাথে ডাকা হয় ।

আমি নিশ্চিত নই যে আমার কাছে কোনও ফাংশন টেমপ্লেটের একটি বিশেষ সংস্করণ জোর করার সিনট্যাক্স আছে। আমি মনে করি আপনি একটি ফাংশন অবজেক্ট হিসাবে পয়েন্টার-টু-ফাংশন ব্যবহার করতে পারেন; সংকলক স্বয়ংক্রিয়ভাবে এটি ঠিক করবে।


0

আমি এমএসভিএস 2013 আরসি মূল্যায়ন করছি, এবং এটি এখানে কিছু ক্ষেত্রে প্রস্তাবিত পূর্ববর্তী কয়েকটি সমাধান সংকলন করতে ব্যর্থ হয়েছে। উদাহরণস্বরূপ, অনেক বেশি ফাংশন প্যারামিটার থাকলে এমএসভিএস "অটো" রিটার্ন সংকলন করতে ব্যর্থ হবে, কারণ একটি নেমস্পেস ইমব্রিকেশন সীমা (আমি সেই তথ্যটি মাইক্রোসফ্টকে সংশোধন করার জন্য প্রেরণ করেছি)। অন্যান্য ক্ষেত্রে, আমাদের ফাংশনের রিটার্নে অ্যাক্সেস প্রয়োজন, যদিও এটি লামদা দিয়েও করা যেতে পারে: নিম্নলিখিত দুটি উদাহরণ একই ফলাফল দেয় ..

apply_tuple([&ret1](double a){ret1 = cos(a); }, std::make_tuple<double>(.2));
ret2 = apply_tuple((double(*)(double))cos, std::make_tuple<double>(.2));

এবং আমার আগে যারা এখানে উত্তর পোস্ট করেছেন তাদের আবারও ধন্যবাদ, আমি এটি ছাড়া এটি অর্জন করতে পারতাম না ... সুতরাং এটি এখানে:

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

// This is a work-around for MSVS 2013RC that is required in some cases
#if _MSC_VER <= 1800 /* update this when bug is corrected */
template<>
struct apply_impl<6> {
    template<typename F, typename T, typename... A>
    static inline auto apply_tuple(F&& f, T&& t, A&&... a)
    -> decltype(std::forward<F>(f)(std::get<0>(std::forward<T>(t)), std::get<1>(std::forward<T>(t)), std::get<2>(std::forward<T>(t)),
           std::get<3>(std::forward<T>(t)), std::get<4>(std::forward<T>(t)), std::get<5>(std::forward<T>(t)), std::forward<A>(a)...)) {
         return std::forward<F>(f)(std::get<0>(std::forward<T>(t)), std::get<1>(std::forward<T>(t)), std::get<2>(std::forward<T>(t)),
           std::get<3>(std::forward<T>(t)), std::get<4>(std::forward<T>(t)), std::get<5>(std::forward<T>(t)), std::forward<A>(a)...);
    }
    template<typename C, typename F, typename T, typename... A>
    static inline auto apply_tuple(C*const o, F&& f, T&& t, A&&... a)
    -> decltype((o->*std::forward<F>(f))(std::get<0>(std::forward<T>(t)), std::get<1>(std::forward<T>(t)), std::get<2>(std::forward<T>(t)),
           std::get<3>(std::forward<T>(t)), std::get<4>(std::forward<T>(t)), std::get<5>(std::forward<T>(t)), std::forward<A>(a)...)) {
         return (o->*std::forward<F>(f))(std::get<0>(std::forward<T>(t)), std::get<1>(std::forward<T>(t)), std::get<2>(std::forward<T>(t)),
           std::get<3>(std::forward<T>(t)), std::get<4>(std::forward<T>(t)), std::get<5>(std::forward<T>(t)), std::forward<A>(a)...);
    }
};
#endif

template<>
struct apply_impl<0> {
    template<typename F, typename T, typename... A>
    static inline auto apply_tuple(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 C, typename F, typename T, typename... A>
    static inline auto apply_tuple(C*const o, F&& f, T&&, A&&... a)
    -> decltype((o->*std::forward<F>(f))(std::forward<A>(a)...)) {
         return (o->*std::forward<F>(f))(std::forward<A>(a)...);
    }
};

// Apply tuple parameters on a non-member or static-member function by perfect forwarding
template<typename F, typename T>
inline auto apply_tuple(F&& f, T&& t)
-> decltype(apply_impl<std::tuple_size<typename std::decay<T>::type>::value>::apply_tuple(std::forward<F>(f), std::forward<T>(t))) {
     return apply_impl<std::tuple_size<typename std::decay<T>::type>::value>::apply_tuple(std::forward<F>(f), std::forward<T>(t));
}

// Apply tuple parameters on a member function
template<typename C, typename F, typename T>
inline auto apply_tuple(C*const o, F&& f, T&& t)
-> decltype(apply_impl<std::tuple_size<typename std::decay<T>::type>::value>::apply_tuple(o, std::forward<F>(f), std::forward<T>(t))) {
     return apply_impl<std::tuple_size<typename std::decay<T>::type>::value>::apply_tuple(o, std::forward<F>(f), std::forward<T>(t));
}

কেন আপনি অবজেক্ট আর্গুমেন্টকে কনস্ট পয়েন্টার করেন? রেফারেন্স নয়, কনস্ট রেফারেন্স নয়, কেবল পয়েন্টার নয়? কল যদি ফাংশন না হয় const?
টাওয়ার 120

0

@ ডেভিডের সমাধানটি প্রসারিত করে আপনি একটি পুনরাবৃত্ত টেম্পলেট লিখতে পারেন যা

  1. (অতিমাত্রায় ভার্বোস, ইমো) integer_sequenceশব্দার্থক শব্দ ব্যবহার করে না
  2. int Nপুনরাবৃত্তীয় পুনরাবৃত্তিগুলি গণনা করতে অতিরিক্ত অস্থায়ী টেম্পলেট প্যারামিটার ব্যবহার করে না
  3. (স্ট্যাটিক / গ্লোবাল ফান্টেক্টরগুলির জন্য )চ্ছিক) সংকলন-কালীন অপ্টিমাইজিয়নের জন্য ফান্টারটিকে একটি টেম্পলেট প্যারামিটার হিসাবে ব্যবহার করে

উদাহরণ:

template <class F, F func>
struct static_functor {
    template <class... T, class... Args_tmp>
    static inline auto apply(const std::tuple<T...>& t, Args_tmp... args)
            -> decltype(func(std::declval<T>()...)) {
        return static_functor<F,func>::apply(t, args...,
                std::get<sizeof...(Args_tmp)>(t));
    }
    template <class... T>
    static inline auto apply(const std::tuple<T...>& t, T... args)
            -> decltype(func(args...)) {
        return func(args...);
    }
};

static_functor<decltype(&myFunc), &myFunc>::apply(my_tuple);

বিকল্প হিসাবে যদি আপনার ফান্টর সংকলন-সময়ে সংজ্ঞায়িত না হয় (যেমন, একটি নন- constexprফ্যাক্টর উদাহরণ, বা ল্যাম্বডা এক্সপ্রেশন), আপনি এটি ক্লাস টেম্পলেট প্যারামিটারের পরিবর্তে ফাংশন প্যারামিটার হিসাবে ব্যবহার করতে পারেন এবং প্রকৃতপক্ষে সংযুক্ত শ্রেণিকে পুরোপুরি সরিয়ে ফেলুন:

template <class F, class... T, class... Args_tmp>
inline auto apply_functor(F&& func, const std::tuple<T...>& t,
        Args_tmp... args) -> decltype(func(std::declval<T>()...)) {
    return apply_functor(func, t, args..., std::get<sizeof...(Args_tmp)>(t));
}
template <class F, class... T>
inline auto apply_functor(F&& func, const std::tuple<T...>& t,
        T... args) -> decltype(func(args...)) {
    return func(args...);
}

apply_functor(&myFunc, my_tuple);

পয়েন্টার-টু-সদস্য-ফাংশন কলযোগ্যদের জন্য, আপনি উপরের কোডের টুকরোগুলির কোনওটিকে @ ডেভিডের উত্তরের মতো একইভাবে সামঞ্জস্য করতে পারেন।

ব্যাখ্যা

কোডের দ্বিতীয় টুকরা রেফারেন্স ইন, দুই টেমপ্লেট ফাংশন আছে: প্রথম এক functor লাগে func, tuple tধরনের সঙ্গে T..., এবং একটি প্যারামিটার প্যাক argsধরনের Args_tmp...। যখন ডাকা হয়, এটি একবার থেকে tপ্যারামিটার প্যাক থেকে একবারে শুরু থেকে (অবধি 0) অবজেক্টগুলিকে যুক্ত করে এবং নতুন বর্ধিত প্যারামিটার প্যাকের সাথে ফাংশনটিকে আবার কল করে।

দ্বিতীয় ফাংশনের স্বাক্ষরটি প্রথমটির সাথে প্রায় সমান, তবে এটি T...প্যারামিটার প্যাকের জন্য টাইপ ব্যবহার করে args। সুতরাং, একবার argsপ্রথম ফাংশনটিতে একবার থেকে মানগুলি সম্পূর্ণরূপে পূর্ণ হয়ে গেলে t, এটি টাইপ হবে T...(পিচিউডো কোডে typeid(T...) == typeid(Args_tmp...)), এবং এইভাবে সংকলকটি দ্বিতীয় ওভারলোডেড ফাংশনটিকে কল করবে, যার ফলে কলগুলি পরিবর্তিত হবে func(args...)

স্থির ফান্টকার উদাহরণের কোডটি একইভাবে কাজ করে, ফান্টারের পরিবর্তে শ্রেণিক টেম্পলেট যুক্তি হিসাবে ব্যবহৃত হয়।


প্রথম বিকল্পটির সংকলন-সময়ের অপ্টিমাইজেশনের বিষয়ে যে কোনও মন্তব্য প্রশংসিত হবে, তাই আমি আমার উত্তর আরও সম্পূর্ণ করতে পারি (এবং সম্ভবত নতুন কিছু শিখতে পারি)।
ক্রেপগোট

-3

আপনার ভ্যারিয়েডিক যুক্তিগুলি কেবলমাত্র একটি টিউপল শ্রেণিতে মুড়ে রাখুন এবং তারপরে আপনার আগ্রহী সূচকটি পুনরুদ্ধার করতে সংকলন সময় পুনরাবৃত্তি ( লিঙ্কটি দেখুন ) ব্যবহার করুন I

template<typename... Args>
auto get_args_as_tuple(Args... args) -> std::tuple<Args...> 
{
    return std::make_tuple(args);
}

6
প্রশ্নটি অন্যদিকে ছিল। না Args...-> tupleকিন্তু tuple-> Args...
জিও

-4

এই সহজ সমাধানটি আমার পক্ষে কাজ করে:

template<typename... T>
void unwrap_tuple(std::tuple<T...>* tp)
{
    std::cout << "And here I have the tuple types, all " << sizeof...(T) << " of them" << std::endl;
}

int main()
{
    using TupleType = std::tuple<int, float, std::string, void*>;

    unwrap_tuple((TupleType*)nullptr); // trick compiler into using template param deduction
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.