2016-05-02 15 views
6

Ho una classe Filter che ha il metodo process sovraccarico per vari input.Alias ​​per tutti i metodi sovraccaricati?

template< typename T > 
class Filter 
{ 
public: 
    void process(T arr[], size_t len); 
    T process(T one_value); 
    void process(std::array &arr); 
    void process(std::vector &v); 
    //... many other variants 

    using operator() = process; // How to write proper? 
} 

voglio semplificare il codice utente omettendo process: filter.process(values) diventerà filter(values). Non penso che scrivere un sovraccarico operator() per ogni variante sia una buona idea. Ci deve essere una soluzione più conveniente?

risposta

7

Poiché si dispone già di modelli nel mix; perché non provare anche un modello variadico;

template <typename... Args> 
auto operator()(Args&&... args) 
// assuming non-reference returns 
{ 
    return process(std::forward<Args>(args)...); 
} 

In alternativa; se i riferimenti vengono restituiti formano alcuni degli overload (non mostrati nell'OP);

template <typename... Args> 
decltype(auto) operator()(Args&&... args) 
// caters for reference returns 
{ 
    return process(std::forward<Args>(args)...); 
} 

Per ulteriori completezza e più ampi casi di utilizzo; se lo si desidera, il seguente comportamento offre un comportamento amichevole con SFINAE e, a seconda del compilatore, messaggi di errore più brevi/più semplici;

template <typename... Args> 
auto operator()(Args&&... args) -> decltype(process(std::forward<Args>(args)...)) 
// SFINAE support using a trailing decltype 
{ 
    return process(std::forward<Args>(args)...); 
} 
+0

Se si desidera completamente bypass tipo controllo dal compilatore e potenzialmente introdurre un sacco di bug sottili, poi certo, andare avanti. –

+2

Non è possibile aggirare alcun tipo di controllo, non ci sono conversioni. 'process' riceverà gli argomenti come forniti a' operator() '. – Niall

+4

@DanKorn Penso che sia piuttosto comune rispondere al tag 'C++' con codice C++ che aderisce allo standard corrente. Cioè, non penso che il tag 'C++' implichi C++ 03 o qualsiasi altro standard specifico. –

8

Certo, basta il template operator(), uso universale di riferimento, e perfetto avanzare gli argomenti da process. di causa, è necessario aggiungere l'intestazione appropriata.

template< typename T > 
class Filter 
{ 
public: 
    void process(T arr[], size_t len); 
    T process(T one_value); 
    void process(std::array &arr); 
    void process(std::vector &v); 
    //... many other variants 

    template<typename... Y> 
    auto operator() (Y&&... y) 
     -> decltype(process(std::declval<Y>()...)) 
    { 
     return process(std::forward<Y>(y)...); 
    } 
} 

Tuttavia, si noti che ogni sovraccarico process deve essere dichiarato prima operator()(...) - Grazie TC

+0

Penso che lascerò la mia risposta ad altre persone per vedere la semplicità della deduzione del tipo di ritorno "auto" del C++ 14 come mostrato nella risposta di Nail. – WhiZTiM

+1

@ T.C. Abbiamo bisogno del 'declval's? Forse solo 'decltype (process (std :: forward (y) ...))'? – Barry

-4

Va bene, si è modificato la domanda, quindi questo risponde quello che stai chiedendo ora, in particolare, "Voglio semplificare il processo di omissione del codice utente: filter.process (valori) diventerà filtro (valori). "

Basta fare tutti quei sovraccarichi in costruttori, invece, in questo modo:

template< typename T > 
class Filter 
{ 
public: 
    void Filter(T arr[], size_t len); 
    T Filter(T one_value); 
    void Filter(std::array &arr); 
    void Filter(std::vector &v); 
    //... many other variants 
}; 
+1

Questo non corrisponde a come l'OP vuole chiamare il filtro. – NathanOliver

Problemi correlati