2012-04-20 31 views
15

Giảm mẫu mã:variadic mẫu với tham số 'const' quá tải

#include <iostream> 

template<typename T> 
void func(T &x) 
{ 
    std::cout << "non-const " << x << std::endl; 
} 

template<typename T> 
void func(const T &x) 
{ 
    std::cout << "const " << x << std::endl; 
} 

template<typename ...ARGS> 
void proxy(ARGS ...args) 
{ 
    func(args...); 
} 

int main() 
{ 
    int i = 3; 

    func(i); 
    func(5); 
    func("blah"); 

    proxy(i); 
    proxy(5); 
    proxy("blah"); 
} 

sản lượng dự kiến:

non-const 3 
const 5 
const blah 
non-const 3 
const 5 
const blah 

đầu ra thực tế:

non-const 3 
const 5 
const blah 
non-const 3 
non-const 5 
non-const blah 

Vì vậy, bằng cách nào đó const vòng loại của hàm tham số bị mất khi đặt qua mẫu variadic. Tại sao? Làm thế nào tôi có thể ngăn chặn điều này?

PS: thử nghiệm với GCC 4.5.1 và SUSE 11,4

+0

Nó không có gì để làm với các mẫu variadic. Các tham số của mẫu chức năng của bạn không tham chiếu, do đó, const của các đối số hàm bị bỏ qua khi suy luận các đối số mẫu. – Cosyn

Trả lời

18

Bạn chỉ cần vấp ngã khi forwarding problem. Vấn đề này được giải quyết bằng cách sử dụng perfect forwarding.

Về cơ bản, bạn cần phải thực hiện các thông số của bạn bằng cách rvalue-tài liệu tham khảo, và dựa vào std::forward để chuyển tiếp một cách chính xác họ trong khi vẫn giữ bản chất của chúng:

template<typename ...Args> 
void proxy(Args&& ...args) 
{ 
    func(std::forward<Args>(args)...); 
} 
+0

Bạn không cần 'std :: forward '? – juanchopanza

+0

@juanchopanza No. Điều đó sẽ chuyển tất cả các đối số kiểu tới 'std :: forward', nhưng' std :: forward' chỉ có một đối số kiểu. –

+0

@ R.MartinhoFernandes Phải, chuyển tiếp cũng chỉ mất một tham số, vì vậy tôi đoán chúng ta cần 'func (std :: forward (args) ...); hoặc một cái gì đó như thế? mẫu trong câu trả lời không biên dịch trên ảnh chụp gcc4.7 của tôi. – juanchopanza

6

Như Lục đã đề cập đây là một vấn đề về chuyển tiếp và câu trả lời đến cách ngăn chặn nó là sử dụng chuyển tiếp hoàn hảo. Nhưng tôi sẽ cố gắng giải quyết các câu hỏi khác ở cuối:

Vì vậy, bằng cách nào đó, trình độ const của thông số chức năng bị mất khi được đưa vào mẫu variadic. Tại sao?

Điều này có mọi thứ cần làm với suy luận kiểu. Bỏ qua mà bạn đang sử dụng mẫu variadic và xem xét các mẫu một đối số đơn giản nhất:

template <typename T> 
void one_arg_proxy(T arg) { 
    func(arg); 
} 

Tại nơi gọi bạn có one_arg_proxy(5), có nghĩa là, các đối số là một intrvalue. Suy luận kiểu đá trong để tìm ra những gì các loại T nên được, và các quy tắc dictate rằng Tint, vì vậy cuộc gọi được dịch sang one_arg_proxy<int>(5) và instantiation của mẫu đó được biên soạn là:

template <> 
void one_arg_proxy<int>(int arg) { 
    func(arg); 
} 

Bây giờ hãy gọi tới số func nhận đối số lvalue và do đó phiên bản func tham chiếu không phải là tham chiếu tốt hơn (không yêu cầu chuyển đổi) so với tham số const&, cho kết quả bạn đang nhận được. Vấn đề ở đây là func không được gọi với đối số là proxy, mà đúng hơn là với bản sao nội bộ mà proxy làm bằng.

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