2016-05-02 9 views
6

У меня есть класс Filter, который имеет метод process, перегруженный для различных входов.Псевдоним для всех перегруженных методов?

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? 
} 

Я хочу, чтобы упростить код пользователя минуя process: filter.process(values) станет filter(values). Я не думаю, что писать перегруженный operator() для каждого варианта - хорошая идея. Должно существовать более удобное решение?

ответ

7

Поскольку у вас уже есть шаблоны в миксе; почему бы не попробовать вариационный шаблон;

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

В качестве альтернативы; если ссылки возвращаются из некоторых перегрузок (не показаны в OP);

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

Для дальнейшей полноты и более широких случаев использования; при желании, следующее предлагает поведение, благоприятное для SFINAE, и в зависимости от компилятора, более короткие/более простые сообщения об ошибках;

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

Если вы хотите полностью байпас проверки типов компилятора и потенциально ввести много тонких ошибки, то конечно, идти вперед. –

+2

В обход каких-либо проверок нет никаких конверсий. 'process' получит аргументы, предоставленные' operator() '. – Niall

+4

@DanKorn Я думаю, что довольно часто приходится отвечать на тег 'C++' кодом C++, который придерживается текущего стандарта. То есть, я не думаю, что тег 'C++' подразумевает C++ 03 или любой другой конкретный стандарт. –

8

Конечно, просто шаблон в operator(), используйте универсальный справочник, и идеально-вперед аргументы process. причины, вам нужно добавить соответствующий заголовок.

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

Однако, обратите внимание, что каждая перегрузка process должна быть объявлена ​​до operator()(...) - Спасибо TC

+0

Я думаю, я просто оставлю свой ответ другим людям, чтобы увидеть простоту расширенного вывода типа 'auto' C++ 14, как показано в ответе Найла. – WhiZTiM

+1

@ T.C. Нужно ли нам вообще «деклавать»? Может быть, просто 'decltype (process (std: forward (y) ...))'? – Barry

-4

Хорошо, вы редактировали этот вопрос, так что это ответ на то, что вы спрашиваете сейчас, в частности, «Я хочу упростить процесс исключения кода пользователя: filter.process (values) станет фильтром (значениями). "

Просто сделать все эти перегруженную в конструкторы вместо этого, например, так:

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

Это не соответствует тому, как OP хочет вызвать фильтр. – NathanOliver

 Смежные вопросы

  • Нет связанных вопросов^_^