2011-02-02 38 views
6

tôi có thể viết một hàm templated cách nàymẫu vượt qua theo giá trị hoặc tham chiếu const hoặc ...?

template<class T> void f(T x) {...} 

hoặc theo cách này

template<class T> void f(T const& x) {...} 

Tôi đoán rằng tùy chọn thứ hai có thể được tối ưu hơn vì nó tránh được một cách rõ ràng một bản sao, nhưng tôi nghi ngờ rằng nó có thể cũng không thành công đối với một số loại cụ thể T (ví dụ: functors?). Vì vậy, khi nào nên sử dụng tùy chọn đầu tiên và khi nào nên sử dụng tùy chọn thứ hai? Ngoài ra còn có boost::call_traits<T>::param_typeboost::reference_wrapper có trong câu trả lời cho số previous question của tôi, nhưng mọi người không sử dụng chúng ở mọi nơi, phải không? Có quy tắc nào cho điều này không? Cảm ơn.

+1

Có nguy cơ tìm kiếm ngu ngốc, tôi phải hỏi: làm thế nào nó có thể thất bại cho một functor? – Beta

+0

@Beta: đó là một phỏng đoán ngẫu nhiên. Nếu ai đó có thể giải thích trong trường hợp nó thực sự có thể thất bại, tôi sẽ được quan tâm. –

+0

Bạn đang cố gắng đạt được điều gì? Nó phụ thuộc vào mã nội bộ trong 'f'. –

Trả lời

11

Có quy tắc nào cho điều này không?

Các quy tắc chung chung khi sử dụng khi vượt qua tham chiếu so với giá trị được áp dụng.

Nếu bạn mong đợi T luôn là loại số hoặc loại rất rẻ để sao chép, thì bạn có thể lấy đối số theo giá trị. Nếu bạn định sao chép đối số vào biến cục bộ trong hàm, thì bạn nên lấy giá trị đó theo giá trị help the compiler elide copies that don't really need to be made.

Nếu không, hãy tham số bằng tham chiếu. Trong trường hợp các loại có giá rẻ để sao chép, nó có thể đắt hơn nhưng đối với các loại khác, nó sẽ nhanh hơn. Nếu bạn thấy đây là điểm phát sóng hiệu năng, bạn có thể quá tải chức năng cho các loại đối số khác nhau và thực hiện điều đúng cho mỗi đối số.

+0

Vì vậy, không có vấn đề mẫu cụ thể nào cả? –

+1

@ 7vies: Không thực sự; "vấn đề" duy nhất là thay vì chỉ có một loại suy nghĩ, bạn phải quyết định điều gì có ý nghĩa đối với nhóm các loại mà mẫu sẽ được sử dụng. –

+0

@ James McNellis: Tôi đoán đôi khi bạn không thể quyết định điều này, ví dụ như STL sẽ chấp nhận các functors theo giá trị, trong khi một người có thể có một functor "rất nhà nước" và điều đó sẽ không hiệu quả. Có nên sử dụng 'boost :: call_traits :: param_type' trong trường hợp này, hay chỉ gắn với giá trị truyền qua như STL đã làm? –

0

Bên cạnh những gì James McNellis đã viết, tôi chỉ muốn nói thêm rằng bạn có thể chuyên mẫu của bạn với nhiều loại tài liệu tham khảo (for example like this)

0

boost::traits có một đặc điểm kiểu đó chọn "tốt nhất" loại, dựa trên T:

call_traits<T>::param_type

Như đã đề cập, không có vấn đề về mẫu cụ thể.

+0

thường trình biên dịch không thể suy ra đối số templpate trong trường hợp này (nó là mẫu cụ thể vấn đề). – user396672

6

tôi nghi ngờ rằng nó cũng có thể thất bại đối với một số loại hình cụ thể

đèo bằng cách tham chiếu đến const là cơ chế qua duy nhất mà "không bao giờ" thất bại. Nó không đặt ra bất kỳ yêu cầu nào trên T, nó chấp nhận cả giá trị và giá trị làm đối số và cho phép chuyển đổi ngầm định.

1

Ngươi chớ đánh thức người chết, nhưng lãnh đạo một vấn đề tương tự và đây là một số mã ví dụ cho thấy làm thế nào để sử dụng những đặc điểm 11s loại C++ để suy luận liệu một tham số nên được thông qua giá trị hoặc tham khảo:

#include <iostream> 
#include <type_traits> 

template<typename key_type> 
class example 
{ 
    using parameter_type = typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type&>::type; 

public: 
    void function(parameter_type param) 
    { 
     if (std::is_reference<parameter_type>::value) 
     { 
      std::cout << "passed by reference" << std::endl; 
     } else { 
      std::cout << "passed by value" << std::endl; 
     } 
    } 
}; 

struct non_fundamental_type 
{ 
    int one; 
    char * two; 
}; 

int main() 
{ 
    int one = 1; 
    non_fundamental_type nft; 

    example<int>().function(one); 
    example<non_fundamental_type>().function(nft); 

    return 0; 
} 

Hy vọng nó sẽ giúp người khác với một vấn đề tương tự.

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