2016-07-06 12 views
31

Załóżmy, że mamy klasy szablonu takiego:Odliczenie funkcji

template<typename F> 
class A 
{ 
public: 
    template<typename... Args> 
    A(F f, Args... args) 
    { /* Do something... */ } 
}; 

a teraz chcę go używać w jakiś sposób podobny do tego:

A<int(int)> a(::close, 1); 

teraz pytanie: czy istnieje sposób, aby pominąć <int(int)>, ponieważ kompilator może znać tę informację dla ::close? Nie ma potrzeby zapisywania "projektu" szablonu.

Co do konkretnego zadania, muszę zaprojektować szablon klasy. Obiekty tej klasy mogą przyjąć funkcję i parametry dla tej funkcji w czasie budowy i wywołać tę funkcję później.

Odpowiedz

35

Nie, ty (obecnie) nie możesz. Standardowym sposobem osiągnięcia tego celu jest stworzenie „make_like” funkcji (takich jak make_pair, make_optional ...):

template<typename F, typename... Args> 
A<std::decay_t<F>> make_A (F &&f, Args&&... args) { 
    return {std::forward<F>(f), std::forward<Args>(args)...}; 
} 

C++ 17 wprowadzi template argument deduction for class który pozwoli Ci dokładnie to, co chcesz zrobić.

+0

Wierzę, że właściwym sposobem wykonania tych funkcji fabrycznych jest użycie 'std :: decay' lub podobnej cechy na' A '. Które sprawiają, że 'A >'. Zobacz http://en.cppreference.com/w/cpp/utility/optional/make_optional lub inne 'make_ *' reference – KABoissonneault

+0

@KABoissonneault Tak, masz rację, jeśli używam uniwersalnych referencji, powinienem używać 'std :: decay' , Zaktualizowałem odpowiedź. – Holt

+0

Nie bardzo rozumiałem pytanie, a zatem odpowiedź. Czy cały cel jest w stanie powiedzieć "auto a (:: close, 1)"? – Assimilater

11

Nie można pominąć argumentów klasy szablonu, chyba że są one domyślne. To, co możesz zrobić, to funkcja producenta, która dedukuje argument i przekazuje ten argument do klasy szablonu, zwracając obiekt odpowiedniej instancji.

template<typename F, typename... Args> 
A<F> make_A(F f, Args&&... args) { 
    return A<F>(f, std::forward<Args>(args)...); 
} 
15

Dzięki przyjęciu szablonu parametr odliczenia dla konstruktorów, w C++ 17, będzie można po prostu napisać:

A a(::close, 1); 

Przedtem, to wystarczy napisać do fabryki odliczenia zrobić dla Ciebie:

template <class F, class... Args> 
A<std::decay_t<F>> make_a(F&& f, Args&&... args) { 
    return {std::forward<F>(f), std::forward<Args>(args)...}; 
} 

auto a = make_a(::close, 1); 

to jest trochę rozwlekły, ale przynajmniej nie trzeba się martwić o wydajności - nie będzie tu kopie wykonane dzięki RVO.

+1

Re: C++ 17: To jest takie dziwne. Wygląda na to, że powinieneś przynajmniej napisać: "A a (:: close, 1);'. Chociaż domyślam się, że przyzwyczaję się do tego. . . – ruakh

Powiązane problemy