2013-06-29 52 views
6

Tôi có mã này ở đây.Vòng lặp dựa trên dải và chức năng nội tuyến

#include <iostream> 
using namespace std; 

template <typename T> inline T bigArry(const T data[5]) 
{ 
    T level = data[0]; 
    for(T item : data) // error C2143: syntax error : missing ',' before ':' (1st) 
    { //error C2143: syntax error : missing ';' before '{' (3rd) 
     if(level<item){ level=item; } 
    } 
    return level; 
} 

int main() 
{ 
    int data[5]={//five variables} 
    cout << bigArry(data);//see reference to function template instantiation 'T bigArry<int>(const T [])' being compiled with [ T=int] (2nd) 

    return 0; 
} 

Hàm bigArry() trả về giá trị cao nhất trong một mảng gồm 5 phần tử.

Vấn đề là khi tôi sử dụng vòng lặp dựa trên phạm vi, nó cung cấp cho tôi các lỗi được đề cập trong mã. Nhưng khi tôi sử dụng bình thường, mọi thứ trở lại bình thường. Ý tôi là, cú pháp đối với tôi có vẻ ổn, tôi không thể thấy được vấn đề. Tôi đang sử dụng Visual Studio 2010.

Điều khác tôi muốn hỏi là về các hàm nội tuyến. Hiện tại tôi đang đọc C++ Primer Plus phiên bản thứ 6. Khi nào tôi biết khi nào một hàm quá lớn để được gạch chân? Có tiêu chuẩn về cách viết mã ngắn không? Hoặc, chúng ta có sử dụng các hàm nội tuyến khi chúng ta "nghĩ" được không?

Cảm ơn bạn, RobertEagle

+0

Không phải lỗi trình biên dịch thứ 2 của bạn có '[T = int]', thay vì 'float'? – yzt

+0

Cách sử dụng 'vector '? – Immueggpain

+0

Nổi đến từ mảng cũ mà tôi đã khai báo. –

Trả lời

7

Tham số data KHÔNG phải là một mảng trong mẫu chức năng của bạn. Nó thực sự là một con trỏ.

Chức năng này

template <typename T> inline T bigArry(const T data[5]) 

chính xác cùng như thế này:

template <typename T> inline T bigArry(const T *data) 

không có khác biệt gì cả.

Đó là lý do tại sao mã của bạn cung cấp lỗi biên dịch.

Có đang vài sửa lỗi ở đây:

  • Bạn có thể chấp nhận lập luận bằng cách tham khảo, như:

    template <typename T> 
    inline T bigArry(const T (&data)[5]) //NOTE & 
    

    Điều đó sẽ làm việc. Nhưng sau đó trông có vẻ cồng kềnh. Có thể, sử dụng tiếp theo.

  • Hoặc bạn có thể sử dụng này (theo đề nghị của @yzt):

    template <typename C> 
    inline auto bigArry(C const & data) -> decltype(data[0]) 
    

    Đây là sạch cũng như linh hoạt hơn so với cái trên (và dưới một). Ngoài mảng đi qua, bạn có thể vượt qua bất kỳ vùng chứa nào miễn là data[0] được xác định rõ và có nghĩa là ý nghĩa của nó.

  • Hoặc nếu bạn muốn, bạn có thể sử dụng std::array<T, 5> như:

    template <typename T> 
    inline T bigArry(const std::array<T,5> & data) 
    

Hy vọng rằng sẽ giúp.

+0

Tôi tin rằng chữ ký này sẽ làm việc với các mảng C thuần túy và một số các thùng chứa khác, bao gồm 'std :: vector's và' std :: array's, và chấp nhận kích thước của mảng được chấp nhận: 'template decltype inline (C [0]) bigArry (C const & dữ liệu) ' – yzt

+0

@yzt: Điểm tốt. :-) – Nawaz

+0

Tôi đề nghị nó ở đây (thay vì trong một câu trả lời khác) để bạn thêm nó vào câu trả lời của bạn, nếu bạn thấy phù hợp. Tôi nghĩ rằng đó là một câu trả lời tốt hơn bằng cách sử dụng 'std :: array' vì nó không yêu cầu một tiêu đề mới. Nhưng nó chắc chắn hơn "rườm rà". – yzt

6

Đó là bởi vì loại mảng phân rã để con trỏ khi được sử dụng như thông số chức năng hoặc khi thông qua như là đối số chức năng. Nói cách khác, chữ ký chức năng của bạn là tương đương với:

template <typename T> inline T bigArry(const T* data) 

Phạm vi dựa trên for lặp đi data cho toàn cầu std::begin()std::end() chức năng để có được vòng lặp để (tương ứng) là người đầu tiên và one- thành phần cuối cùng của vùng chứa.

Tất nhiên, không có toàn cầu std::begin()std::end() chức năng chấp nhận một con trỏ , và họ không thể được xác định có ý nghĩa hoặc là: làm thế nào để xác định cuối container được chỉ là một con trỏ đến phần tử đầu tiên của mình?

Bạn có thể sử dụng std::array thay vì mảng C (std::array là một wrapper zero-overhead xung quanh một mảng C), và sửa đổi chức năng gọi điện thoại của bạn cho phù hợp:

template <typename T> inline T bigArry(std::array<T, 5> data) 
//          ^^^^^^^^^^^^^^^^ 
{ 
    T level = data[0]; 
    for(T item : data) 
    { 
     if(level<item){ level=item; } 
    } 
    return level; 
} 

int main() 
{ 
    std::array<int, 5> data = {1,2,3,4,5}; 
// ^^^^^^^^^^^^^^^^^^^^^^^ 
    std::cout << bigArry(data); 

    return 0; 
} 

Đây là một live example.

+0

Tôi tin rằng chữ ký này sẽ làm việc với các mảng C thuần túy và một số vùng chứa khác, bao gồm 'std :: vector's và' std :: array's : 'template inline decltype (C [0]) bigArry (C const & dữ liệu) {...}' – yzt

+0

@Andy: Trên thực tế [các quy tắc cho các dấu ngoặc nhọn] (http://stackoverflow.com/questions/ 11734861/khi-có thể-bên ngoài-niềng răng-được-bỏ-trong-một-initializer-danh sách) là một chút bối rối ở lần. Nhưng những gì tôi đã nói trước đây không áp dụng trong trường hợp này. – Nawaz

+0

@Nawaz: OK, cảm ơn bạn đã liên kết –

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