Bunu en zarif çözüm olarak görüyorum (ve en iyi şekilde yönlendiriliyor):
#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));
}
Örnek kullanım:
void foo(int i, bool b);
std::tuple<int, bool> t = make_tuple(20, false);
void m()
{
apply(&foo, t);
}
Ne yazık ki GCC (en az 4.6) bunu "üzgün, uygulanmamış: aşırı yükleme" ile derleyemedi (bu sadece derleyicinin henüz C ++ 11 spesifikasyonunu tam olarak uygulamadığı anlamına gelir) ve varyasyon şablonları kullandığından MSVC'de çalışır, bu yüzden az çok işe yaramaz. Ancak, spesifikasyonu destekleyen bir derleyici varsa, en iyi yaklaşım IMHO olacaktır. (Not: GCC'deki eksiklikler üzerinde çalışabilmeniz veya Boost Preprocessor ile uygulayabilmeniz için bunu değiştirmek zor değil, ancak zarafeti bozuyor, bu yüzden yayınladığım sürüm bu.)
GCC 4.7 artık bu kodu gayet iyi destekliyor.
Düzenleme: Clang kullanıyor olmanız durumunda (veya başka herhangi bir kişi gerçekten eklemek için etrafta dolanırsa), rvalue referans formunu * desteklemek için gerçek işlev çağrısı etrafında ileri eklendi.
Düzenleme: Üye olmayan uygula işlevinin gövdesindeki işlev nesnesi etrafında eksik ileri eklendi. Eksik olduğuna işaret ettiği için pheedbaq'a teşekkürler.
Düzenleme: Ve işte C ++ 14 sürümü sadece çok daha güzel olduğu için (aslında derlemiyor):
#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));
}
Üye işlevleri için bir sürüm (çok fazla test edilmedi!):
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);
}