2013-08-22 33 views
9

Tôi muốn gọi phương thức từ phương thức khác, thông qua chức năng của bên thứ ba; nhưng cả hai đều sử dụng các mẫu variadic. Ví dụ:Làm thế nào để kết hợp std :: bind(), mẫu variadic và chuyển tiếp hoàn hảo?

void third_party(int n, std::function<void(int)> f) 
{ 
    f(n); 
} 

struct foo 
{ 
    template <typename... Args> 
    void invoke(int n, Args&&... args) 
    { 
    auto bound = std::bind(&foo::invoke_impl<Args...>, this, 
          std::placeholders::_1, std::forward<Args>(args)...); 

    third_party(n, bound); 
    } 

    template <typename... Args> 
    void invoke_impl(int, Args&&...) 
    { 
    } 
}; 

foo f; 
f.invoke(1, 2); 

Vấn đề là, tôi nhận được một lỗi biên dịch:

/usr/include/c++/4.7/functional:1206:35: error: cannot bind ‘int’ lvalue to ‘int&&’ 

tôi đã cố gắng sử dụng một lambda, nhưng maybe GCC 4.8 không xử lý các cú pháp được nêu ra; đây là những gì tôi đã cố gắng:

auto bound = [this, &args...] (int k) { invoke_impl(k, std::foward<Args>(args)...); }; 

tôi nhận được lỗi sau:

error: expected ‘,’ before ‘...’ token 
error: expected identifier before ‘...’ token 
error: parameter packs not expanded with ‘...’: 
note:   ‘args’ 

Từ những gì tôi hiểu, trình biên dịch muốn nhanh chóng invoke_impl với loại int&&, trong khi tôi nghĩ rằng việc sử dụng && trong trường hợp này sẽ bảo toàn loại đối số thực tế.

Tôi đang làm gì sai? Cảm ơn,

+0

GCC 4.8 xử lý cú pháp một cách hoàn hảo. Bạn đã thử gì? –

+0

@ArneMertz Tôi đã cập nhật câu hỏi với cú pháp tôi đã thử – piwi

+0

có vẻ như bạn vừa gặp lỗi trong gcc, nó sẽ hoạt động: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41934 –

Trả lời

6

Ràng buộc với &foo::invoke_impl<Args...> sẽ tạo một hàm ràng buộc có tham số Args&&, có nghĩa là một giá trị. Vấn đề là thông số được chuyển sẽ là một số lvalue vì đối số được lưu trữ dưới dạng hàm thành viên của một số lớp nội bộ.

Để khắc phục, hãy sử dụng quy tắc thu gọn tham chiếu bằng cách thay đổi &foo::invoke_impl<Args...> thành &foo::invoke_impl<Args&...> để chức năng thành viên sẽ nhận giá trị.

auto bound = std::bind(&foo::invoke_impl<Args&...>, this, 
         std::placeholders::_1, std::forward<Args>(args)...); 

Here is a demo.

+0

Thực ra, có vẻ như rằng giải pháp này không hoạt động nếu tôi sử dụng 'std :: reference_wrapper' làm đối số, đây là một ví dụ: http://ideone.com/VBxfZd; sao tôi thiếu một cái gì đó liên quan đến việc sử dụng các trình bao bọc tham chiếu? – piwi

+0

@piwi Sau đó thay đổi 'Args & ...' thành 'Args const & ...'. Không hoàn toàn chắc chắn lý do tại sao nó hoạt động mặc dù. – 0x499602D2

+0

xấu của tôi, tôi có thể đã đưa ra điều này ;-) Cảm ơn. – piwi