2016-05-02 18 views
6

Tôi có một lớp Filter có phương thức process bị quá tải cho các đầu vào khác nhau.Bí danh cho tất cả các phương thức quá tải?

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

Tôi muốn đơn giản hóa mã người dùng bỏ qua process: filter.process(values) sẽ trở thành filter(values). Tôi không nghĩ rằng viết một quá tải operator() cho mỗi biến thể là ý tưởng tốt. Phải tồn tại một giải pháp thuận tiện hơn?

Trả lời

7

Vì bạn đã có các mẫu trong danh sách kết hợp; tại sao không thử một mẫu variadic là tốt;

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

Cách khác; nếu tài liệu tham khảo được trả về dạng một số quá tải (không được hiển thị trong OP);

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

Để hoàn chỉnh hơn nữa và các trường hợp sử dụng rộng hơn; nếu muốn, phần sau đây cung cấp hành vi thân thiện với SFINAE và tùy thuộc vào trình biên dịch, các thông báo lỗi ngắn hơn/dễ dàng hơn;

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

Nếu bạn muốn hoàn toàn bỏ qua loại kiểm tra bởi trình biên dịch và có khả năng giới thiệu rất nhiều lỗi vi tế, sau đó chắc chắn, đi trước. –

+2

Không bỏ qua bất kỳ kiểm tra loại nào, cũng không có chuyển đổi nào. 'process' sẽ nhận các đối số như được cung cấp cho toán tử'() '. – Niall

+4

@DanKorn Tôi nghĩ rằng nó khá phổ biến để trả lời thẻ 'C++' với mã C++ tuân thủ tiêu chuẩn hiện tại. Đó là, tôi không nghĩ rằng thẻ 'C++' ngụ ý C++ 03 hoặc bất kỳ tiêu chuẩn cụ thể nào khác. –

8

Chắc chắn, Chỉ cần template các operator(), sử dụng Universal tham khảo, và hoàn hảo về trước đối số cho process. nguyên nhân, bạn cần thêm tiêu đề thích hợp.

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

Tuy nhiên, lưu ý rằng tất cả các tình trạng quá tải của process phải được khai báo trước khi operator()(...) - Cảm ơn TC

+0

Tôi nghĩ, tôi sẽ để lại câu trả lời cho những người khác để thấy sự đơn giản của việc khấu trừ kiểu tự động trả về 'auto' của C++ 14 như thể hiện trong câu trả lời của Nail. – WhiZTiM

+1

@ T.C. Chúng ta có cần 'từ chối 'không? Có lẽ chỉ 'decltype (process (std :: forward (y) ...))'? – Barry

-4

Được rồi, bạn thay đổi nội dung các câu hỏi, vì vậy đây trả lời những gì bạn đang yêu cầu hiện nay, đặc biệt, "Tôi muốn đơn giản hóa quá trình bỏ qua mã người dùng: filter.process (giá trị) sẽ trở thành bộ lọc (giá trị). "

Chỉ cần làm cho tất cả những quá tải thành nhà thầu thay vào đó, như vậy:

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

Điều này không khớp với cách OP muốn gọi bộ lọc. – NathanOliver

Các vấn đề liên quan