2016-07-06 70 views
31

Diciamo che abbiamo un modello di classe come questo:Deduzione della funzione

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

E ora voglio usare in qualche modo simile a questo:

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

Ora la domanda è: c'è un modo per omettere lo <int(int)> perché un compilatore può conoscere queste informazioni per lo ::close? Non è necessario salvare il "design" del modello.

Per quanto riguarda il compito concreto, ho bisogno di progettare un modello di una classe. Gli oggetti di questa classe potrebbero prendere una funzione e parametri per questa funzione in fase di costruzione e chiamare questa funzione in un secondo momento.

risposta

35

No, non è possibile (al momento). Il modo standard di fare questo è attraverso la creazione di funzione "make_like" (come ad esempio 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 introdurrà template argument deduction for class che vi permetterà di fare esattamente quello che vuoi.

+0

Credo che il modo corretto per eseguire tali funzioni di fabbrica sia usare 'std :: decay' o un tratto simile su' A '. Il che renderebbe 'A >'. Vedi http://en.cppreference.com/w/cpp/utility/optional/make_optional o altro 'make_ *' riferimento – KABoissonneault

+0

@KABoissonneault Sì hai ragione, se uso riferimenti universali dovrei usare 'std :: decay' , Ho aggiornato la risposta. – Holt

+0

Non ho capito bene la domanda, e quindi la risposta. L'intero obiettivo è quello di poter dire "auto a (:: chiudi, 1)'? – Assimilater

11

Non è possibile omettere gli argomenti di una classe modello, a meno che non siano predefiniti. Quello che puoi fare è avere una funzione maker che deduce l'argomento e inoltra questo argomento alla classe template, restituendo un oggetto dell'istanza appropriata.

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

Grazie all'adozione del modello di parametri detrazione per i costruttori, in C++ 17, sarete in grado di scrivere solo:

A a(::close, 1); 

Prima di allora, ti basta scrivere una fabbrica per fare la detrazione per voi:

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

Questo è un po 'prolisso, ma almeno non è necessario preoccuparsi di efficienza - non ci saranno copie fatte qui grazie alla RVO.

+1

Re: C++ 17: È davvero strano. Sembra che dovresti almeno scrivere 'A a (:: chiudi, 1);'. Anche se immagino che mi ci abituerò. . . – ruakh