2016-04-11 36 views
5

wiem, że mogę to zrobić:szablonu parametr - wskaźnik z funkcji o zmiennej liczbie argumentów argumentów

template<typename T, typename Ret, typename A1, typename A2, Ret(T::*F)(A1, A2)> 
class C{} 

Ale jak widać to A1 i A2 są nieco brzydki. W rzeczywistości nie znam liczby argumentów. Brzmi jak praca dla szablonów variadycznych. Niestety nie mogę tego zrobić:

// doesn't work - parameter pack must appear at the end of the template parameter list 
template<typename T, typename Ret, typename... Args, Ret(T::*F)(Args...)> 
class C{} 

Nor to:

szablon klasy C;

// doesn't work - wrong syntax 
template<typename T, typename F, typename Ret, typename... Args> 
class Delegate2<Ret(T::*F)(Args...)>{} 

Czy chcę za dużo?

Odpowiedz

4

Można wykonać następujące czynności:

template<typename T, T> struct C; 

template<typename T, typename R, typename ...Args, R (T::*F)(Args...)> 
struct C<R (T::*)(Args...), F> { 

    R operator()(T &obj, Args &&... args) { 
    return (obj.*F)(std::forward<Args>(args)...); 
    } 

}; 

a potem w swoim programie:

struct A { 
    int foo(int i) { return i; } 
}; 

int main() { 
    C<int(A::*)(int), &A::foo> c; 
    A a; 
    std::cout << c(a, 42) << std::endl; 
} 

Live Demo

+0

Ładne, naprawdę ładne. Wygląda na to, że chciałem, dziękuję, pomyślałem, że najpierw muszę zrozumieć, jak to działa. Dlaczego używam 'template '? Dlaczego 'template ' i specjalizacja 'szablon struct C ' nie działa? – nikitablack

4
template<class T>struct tag{using type=T;}; 
template<class Tag>using type=typename Tag::type; 

template<class T, class Sig> 
struct member_function_pointer; 
template<class T, class Sig> 
using member_function_pointer_t=type<member_function_pointer<T,Sig>>; 

template<class T, class R, class...Args> 
struct member_function_pointer<T, R(Args...)>: 
    tag<R(T::*)(Args...)> 
{}; 

następnie

template<class T, class Sig, member_function_pointer_t<T,Sig> mf> 
class C{}; 

powinien załatwić sprawę. Jeśli potrzebujesz dostępu do Args..., możesz specjalizować się.

template<class T, class Sig, member_function_pointer_t<T,Sig> mf> 
class C; 
template<class T, class R, class...Args, member_function_pointer_t<T,R(Args...)> mf> 
class C<T, R(Args...), mf> { 
}; 

w ten sposób.

+0

Dziękuję. Wygląda dobrze i przerażająco. Ledwo rozumiem, co się dzieje. Czy możesz przynieść trochę światła na twoje podejście? Rzeczą, która przyciąga moje oko, jest dziedzictwo. Nie jestem przeciwko temu, ale mieszanie szablonów i oop sprawia, że ​​rzeczy są bardziej skomplikowane. – nikitablack

+1

@nikitablack Dziedziczenie jest właśnie tam, więc nie muszę wpisywać '{using type = bla; } ', zamiast tego po prostu dziedziczę po': tag {} '. Podczas metaprogramowania często używam wzorca 'template struct some_specialization : is_really_this_solution {}'. – Yakk

Powiązane problemy