Tak, to jest możliwe:
// we need a compile-time helper to generate indices
template< std::size_t... Ns >
struct indices
{
typedef indices< Ns..., sizeof...(Ns) > next;
};
template< std::size_t N >
struct make_indices
{
typedef typename make_indices< N - 1 >::type::next type;
};
template<>
struct make_indices<0>
{
typedef indices<> type;
};
Z tych pomocników, trzeba jedną spedytora dla swojej funkcji tak:
template<typename R, typename... Args, std::size_t... Ns>
R myFunctionImpl(void *Data, void *function, indices<Ns...>) {
auto f = (R (*)(Args...))function;
return f(read<Args>(Data, Ns + 1)...);// +1 because indices is zero-based
}
template<typename R, typename... Args>
R myFunction(void *Data, void *function) {
return myFunctionImpl< R, Args... >(Data, function, typename make_indices<sizeof...(Args)>::type());
}
EDIT: Jak to działa? Najpierw określamy rozmiar modelu do. make_indices<N>::type
następnie rozszerza się do indices<0,1,2,...,N-1>
. Jest on podany jako dodatkowy parametr do funkcji implementacji (od forwardera, który właśnie tworzy fałszywą instancję), stąd odjęcie argumentu od strony funkcji implementacji i umieszcza wygenerowane indeksy w pakiecie argumentów Ns
.
Funkcja implementacji ma teraz dwa zestawy argumentów o tym samym rozmiarze, a mianowicie Args
i Ns
. Po rozwinięciu przez ellipsis ...
, elipsa rozszerza całe wyrażenie , które jest stosowane do niego i rozszerza wszystkie pakiety parametrów równolegle! W powyższym przykładzie to wyrażenie to read<Args>(Data, Ns+1)
, które ładnie rozwija się do pseudokodu OP.
Jestem pewien, że można uniknąć wskazywania obiektu do rzutowania za pomocą wskaźnika funkcji. – sellibitze
@sellibitze: Czy to jest problem? Ponieważ mogę mieć tylko puste dane użytkownika wskaźnika, które są przekazywane z funkcji C. –
Dane mogą być "void *". To funkcja, która jest "pustką", jest problemem. –