2015-12-21 22 views
17

Khi viết các chức năng chung cho "lặp" dao động tôi thường làm:suy ra loại mẫu gõ vào C++

template <typename Iter> auto func(Iter &first, Iter &last) 
{ 
    using IterType = typename std::decay<decltype(*first)>::type; 
    ... 
} 

Một cách khác có vẻ là:

template <typename Iter> auto func(Iter &first, Iter &last) 
{ 
    using IterType = typename std::iterator_traits<Iter>::value_type; 
    ... 
} 

Chưa hết một phần ba:

template <typename Iter> auto func(Iter &first, Iter &last) 
{ 
    using IterType = typename Iter::value_type; 
    ... 
} 

Không áp dụng iterator_traits.

Về lý thuyết, chức năng của tôi chỉ nhận được trình lặp như firstlast và dạng thứ hai lý tưởng nhất (imho) là cách thành ngữ nhất để nhận loại. Nhưng đang sử dụng typename std::decay<decltype(*first)>::type thành ngữ chung nhất để không áp đặt các hạn chế đối với Iter như đã định nghĩa value_type?

+6

Tôi nghĩ rằng đó là thành ngữ để chuyển các trình vòng lặp theo giá trị. – Lingxi

+4

Nếu 'iterator_traits' không hoạt động đối với một cái gì đó, nói điều gì đó không phải là một trình lặp. –

Trả lời

22

Thứ hai là thành ngữ thành ngữ nhất.

  • Đầu tiên không làm việc với proxy (std :: vector < bool>)
  • Thứ ba không làm việc với con trỏ.
10

Không ai trong số này là khá thành ngữ; bạn nên vượt qua vòng lặp theo giá trị, không phải bằng tham chiếu. Dưới đây là chữ ký cho for_each trong gcc 4.9:

template<typename _InputIterator, typename _Function> 
_Function 
for_each(_InputIterator __first, _InputIterator __last, _Function __f) 

Như bạn có thể thấy, nó được truyền theo giá trị. Các chức năng của bạn sẽ không hoạt động khi sử dụng thành ngữ:

func(v.begin(), v.end()); // error, binding non-const ref to rvalue! 

Ngoài ra, thông qua iterator_traits không chỉ là thành ngữ, về cơ bản là bắt buộc. Trong trường hợp STL có liên quan, các typedef được định nghĩa chỉ thông qua iterator_traits: http://en.cppreference.com/w/cpp/concept/ForwardIterator. iterator_traits cung cấp các giá trị mặc định hợp lý cho trường hợp chung, nhưng nó có thể chuyên biệt (vì nó là dành cho con trỏ) để làm những việc khác nhau. Không phải thông qua iterator_traits về cơ bản có nghĩa là ai đó có thể viết một trình lặp tương thích làm việc với STL nhưng không phải mã của bạn.

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