2013-06-29 16 views
6

Mam tutaj ten kod.Funkcje pętli szeregowych i funkcji Inline

#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; 
} 

Funkcja bigArry() zwraca najwyższą wartość z tablicy 5 elementów.

Problem polega na tym, że gdy używam pętli opartych na odległościach, daje mi to błędy wymienione w kodzie. Ale kiedy używam zwykłego, wszystko wraca do normy. Mam na myśli, składnia do mnie wygląda dobrze, nie widzę problemu. Używam Visual Studio 2010.

Kolejna rzecz, o którą chcę zapytać, to funkcje wbudowane. Obecnie czytam C++ Primer Plus 6. wydanie. Kiedy dowiem się, kiedy funkcja jest zbyt duża, aby można ją było założyć? Czy istnieje standard, jak krótki powinien być kod? Czy używamy funkcji wbudowanych, gdy "myślimy", że wszystko jest w porządku?

Dziękuję RobertEagle

+0

Czy Twój drugi błąd kompilatora nie powinien mieć wartości "[T = int]" zamiast "float"? – yzt

+0

Co powiesz na użycie 'wektora '? – Immueggpain

+0

Pływak pochodzi ze starej tablicy, którą zadeklarowałem. –

Odpowiedz

7

Parametr data NIE jest tablicą w szablonie funkcji. Jest to właściwie wskaźnik.

Ta funkcja

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

jest dokładnie taki sam jak ten:

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

nie ma żadnej różnicy w ogóle.

Jest to powód, dla którego Twój kod daje błąd kompilacji.

Są tam kilka poprawek tutaj:

  • Można przyjąć argumentu przez referencję, jak:

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

    który powinien działać. Ale wtedy wygląda to nieporęcznie. Może, użyj następnego.

  • Albo można użyć tego (jak sugeruje @yzt):

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

    To jest czyste, jak również bardziej elastyczne niż jeden powyżej (i poniżej jednego). Oprócz przekazywania tablic, możesz przekazać dowolny kontener, o ile data[0] jest dobrze zdefiniowany i oznacza to, co miał na myśli.

  • lub jeśli chcesz, możesz użyć std::array<T, 5> jak:

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

nadzieję, że pomoże.

+0

Wierzę, że ten podpis będzie działał z prostymi tablicami C i niektórymi innymi kontenerami, w tym 'std :: vector's i' std :: array', i jest bardziej permisywny w rozmiarze tablic, który akceptuje: 'szablon wbudowany dekltype (C [0]) bigArry (C const & data) ' – yzt

+0

@yzt: Dobra uwaga. :-) – Nawaz

+0

Proponuję to tutaj (zamiast w innej odpowiedzi), aby dodać go do swojej odpowiedzi, jeśli uznasz to za stosowne. Myślę, że jest to lepsza odpowiedź niż użycie 'std :: array', ponieważ nie wymaga nowego nagłówka. Ale z pewnością jest bardziej "kłopotliwy". – yzt

6

to dlatego typy tablic rozkładu do wskaźników stosowanych jako parametrów funkcji lub gdy przekazana jako argument funkcji. Innymi słowy, funkcja podpis jest równoważny:

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

Zakres oparte for pętla przechodzi data do światowych std::begin() i std::end() funkcji w celu uzyskania iteratory do (odpowiednio) pierwszy i jedno- ostatni element kontenera.

Oczywiście, nie ma globalnych std::begin() i std::end() funkcje, które akceptują wskaźnik, i nie mogli być sensownie zdefiniowane albo: jak określić koniec danego kontenera tylko wskaźnik do jej pierwszego elementu?

Można użyć std::array zamiast tablic C (std::array jest zero-napowietrznych otoki wokół tablicy C) i zmodyfikować funkcję telefonicznej odpowiednio:

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; 
} 

Oto live example.

+0

Wierzę, że ten podpis będzie działać z zwykłymi tablicami C i niektórymi innymi kontenerami, w tym 'std :: vector's i' std :: array's : 'template inline decltype (C [0]) bigArry (C const & data) {...}' – yzt

+0

@Andy: Właściwie [zasady dla nawiasów klamrowych] (http://stackoverflow.com/questions/ 11734861/when-can-outer-braces-be-omitted-in-an-initialiser-list) są czasami nieco mylące. Ale to, co powiedziałem wcześniej, nie ma zastosowania w tym przypadku. – Nawaz

+0

@Nawaz: OK, dziękuję za link –

Powiązane problemy