2013-05-08 34 views
19

Một số phép biến đổi kiểu trong <type_traits> cũng có thể được biểu diễn bằng cú pháp ngôn ngữ chính (ví dụ: std::add_const<T>::type là/có vẻ tương đương với const T). Dtto cho std::add_lvalue_reference và có thể là những người khác. Việc sử dụng cho những đặc điểm kiểu này là gì?Các trường hợp sử dụng cho tiêu chuẩn :: add_const và tương tự

tôi hoàn toàn hiểu tiêu chuẩn sẽ được cung cấp một "hộp công cụ không đầy đủ" mà không có họ, và tôi có thể tưởng tượng được sử dụng một cách meta, một cái gì đó như thế này:

template<typename In, template <typename> class Modifier> 
struct Apply { 
    typedef typename Modifier<T>::type Out; 
}; 

Apply<int, std::add_const> 

Có bất kỳ trường hợp sử dụng khác cho những đặc điểm mà có thể được thể hiện bằng cú pháp, hoặc là chúng chỉ bao gồm "ngoài ý nghĩa của sự hoàn chỉnh" và cho việc sử dụng meta không thường xuyên?

+1

Điều gì xảy ra nếu 'T' đã là' const'? –

+1

@PeterWood [hoạt động tốt] (http://ideone.com/mhY62n), ít nhất là trong gcc 4.7.2 – Angew

+2

@PeterWood Nếu đó là đã đủ điều kiện, nó mang lại cho cùng loại trở lại, theo yêu cầu của tiêu chuẩn. – jrok

Trả lời

19

Những đặc điểm xuất phát từ Boost và đề nghị để thêm chúng vào các tiêu chuẩn, N1345, trích Andrei Alexandrescu nói:

"Tôi hiểu đối số đối xứng để thêm add_const, add_volatile, add_cv, và add_pointer, tuy nhiên tôi sẽ tranh luận ủng hộ việc loại bỏ chúng. Các ngôn ngữ tương đương được cung cấp chỉ đơn giản và đẹp hơn. "

Đề xuất này cũng mang đến cho lý do này:

của tác giả Lưu ý: một cách hời hợt các add_const, add_volatile và add_cv lớp là không thích hợp, từ đó, ví dụ, add_const :: loại cũng giống như T const, cho tất cả T (hiện tại điều này không áp dụng cho các loại chức năng - nhưng issue 295 giải quyết vấn đề này). Tuy nhiên, kinh nghiệm từ việc tăng cường là một số người dùng đã yêu cầu các mẫu này xuất hiện trong thư viện vì các lý do sau: (a) Một số người dùng thấy rõ hơn - khi kết hợp các mẫu chuyển đổi đặc biệt, người dùng thích loại "được tích hợp sẵn tài liệu "mà các mẫu này cung cấp. (b) Không phải tất cả người dùng đều biết rằng cv-đủ điều kiện tham chiếu được cho phép và không có hiệu lực hoặc cv-đủ điều kiện loại đã đủ điều kiện cv được phép và không có hiệu lực. (c) Trình biên dịch có thể phát ra cảnh báo khi cv-loại một loại tham chiếu, hoặc đã có một vòng loại cv, các mẫu này có thể được thực hiện sao cho các thông điệp này bị chặn trong các trường hợp này.

Ngoài ra, đối add_reference (đổi tên thành add_lvalue_reference trong tiêu chuẩn):

của tác giả Lưu ý: mẫu add_reference là một trong những động lực ban đầu phía sau thư viện đặc điểm tăng loại. Tuy nhiên, độ phân giải issue 106 làm cho mẫu xuất hiện phần lớn dư thừa. Mặc dù add_reference đó cũng có thể hữu ích trong việc ngăn chặn các cảnh báo trình biên dịch khi vô tình tạo tham chiếu tới các tham chiếu trong mã mẫu.

+4

' add_ {l, r} value_reference' cũng đóng độc đáo với 'void' . – Xeo

5

Những đặc điểm này được cung cấp cho việc sử dụng meta không thường xuyên. Nó làm cho nó có thể vận chuyển muốn vòng loại cv xung quanh trong lập trình meta.

template<class T,template<class> class Trait> 
struct transform 
{ 
    /* working with T creating newT*/ 

    typedef Trait<newT>::type type; 
}; 

template<class T> 
struct special_transform 
    : transfrom<T, std::add_const> 
{}; 

Trong trường hợp này, bạn không thể thay thế std::add_const với const.

1

Các trường hợp sử dụng duy nhất tôi biết được minh họa dưới đây:

struct F 
{ 
    bool f() const { return true; } 
    bool f() { return false; } 
}; 
assert(!F{}.f()) 
assert(std::add_const_t<F>{}.f()); 

Nó cũng cần thiết cho việc thử nghiệm của cv-ref có trình độ năng viên-chức năng, có thể khác cho overloadings khác nhau (chỉ dành cho lref- có trình độ C++ hiện đại có ích std::as_const chức năng):

struct F 
{ 
    int g() & { return 1; } 
    int g() const & { return 2; } 
    int g() && { return 3; } 
    int g() const && { return 4; } 
}; 
F f; 
assert(f.g() == 1); 
assert(std::as_const(f).g() == 2); 
assert(F{}.g() == 3); 
assert(std::add_const_t<F>{}.g() == 4); // rarely needed, but if needed, then it helps 
1

add_const có thể được sử dụng để giải quyết mâu thuẫn loại trừ.

template <typename T> 
class wrapper; 

template <typename T> 
bool operator==(wrapper<T> const& w, T const& t); 

vấn đề phát sinh nếu chúng tôi sử dụng wrapper<T const>:

wrapper<int const> w = { 42 }; 
assert(w == 42); // Error: conflicting deduced types 

T được đồng thời suy luận là cả hai intint const. Điều này có thể được giải quyết bằng cách sử dụng add_const:

template <typename T> 
bool operator==(wrapper<T> const& w, add_const_t<T>& t); 
+0

Trường hợp sử dụng thú vị. Bất cứ điều gì khác mà có thể làm cho tham số hàm thứ hai một bối cảnh không suy luận cũng sẽ làm việc, nhưng điều này khá ngắn gọn. – Angew

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