c++ troligen lätt om man arbetat med tamplate-

Permalänk
Medlem

c++ troligen lätt om man arbetat med tamplate-

Hej!

jag sitter och försöker få en template funktion med shellsort att funka jag tror jag inte riktigt förståt hur template funkar än.
detta är mina koder:
main.cpp

#include <iostream> #include <vector> #include <algorithm> #include <time.h> #include "funk.h" #include "shellsort.h" using namespace std; int main() { srand(time(NULL)); const int m=1000000; vector<int> v(m); generate(v.begin(), v.end(), randomNumber); shellsort(v); }

shellsort

#include <vector> template<class T> void shellsort(std::vector<T> &a) { int j; const int gap[8]={701, 301, 132, 57, 23, 10, 4, 1}; for(short int x = 0; x<8; x++) { for(unsigned int i = gap[x]; i < a.size(); i++) { T tmp = a[i]; for(j=i; j>=gap[x] && tmp < a[j-gap[x]]; j-= gap[x]) { a[j] = a[j-gap[x]]; } a[j] = tmp; } } }

behöver ni .h filen och random nummer så säg till iaf när jag kompilerar får jag fel meddelandet:

g++ -o test main.cpp shellsort.cpp randomNumber.cpp
/tmp/ccZbjzn7.o: In function `main':
main.cpp:(.text+0x8c): undefined reference to `void shellsort<int>(std::vector<int, std::allocator<int> >&)'
collect2: ld returned 1 exit status
make: *** [comp] Error 1

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Medlem

Har du inkluderat .cpp filen med din template-funktion? Kan göras längst ner i .h filen som deklarerar funktionen.

Permalänk

Ska inte shellsort<int>(v); vara shellsort(v);?

Visa signatur

Citera, tack!
Har du läst tråden om strandhögtalare och andra musiklådor?

Permalänk
Medlem

blomqvist, de har jag testa funkar ändå inte...

Thomas H, inte riktigt säker på hur de menar? :S

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Medlem

Jag lyckades lösa de, största fellet var att jag definerade shellsort.h som shellsort i #define och lite små saker men nu är de löst.
main

#include <iostream> #include <vector> #include <algorithm> #include <time.h> #include "funk.h" #include "shellsort.h" using namespace std; int main() { srand(time(NULL)); const int m=1000000; vector<int> v(m); generate(v.begin(), v.end(), randomNumber); shellsort(v); for(vector<int>::iterator it=v.begin(); it != v.end(); it++) { cout << (*it) << endl; } }

funk.h

#ifndef funk #define funk int randomNumber(); #endif

randomNumber

#include <algorithm> int randomNumber() { return (rand()); }

shellsort

#ifndef SORT #define SORT #include <vector> #include <functional> using namespace std; template <typename T> void shellsort(vector<T> & a) { int j; const int gap[8]={701, 301, 132, 57, 23, 10, 4, 1}; for(short int x = 0; x<8; x++) { for(unsigned int i = gap[x]; i < a.size(); i++) { T tmp = a[i]; int j=i; for(;j >= gap[x] && tmp < a[ j - gap[x]]; j -= gap[x]) a[j] = a[j - gap[x]]; a[j] = tmp; } } } #endif

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Medlem
Skrivet av blomqvist:

Ska inte shellsort<int>(v); vara shellsort(v);?

Fungerar med båda, vad jag vet.

Skrivet av Mejan:

Thomas H, inte riktigt säker på hur de menar? :S

Vad jag kommer ihåg så kan man inte kompilera filer med templates som man gör med vanliga filer (g++ fil1.cpp templatefil.cpp), utan måste köra include på .cpp filen med templates i koden, vilket lämpligast görs i .h filen. Nu skrev du ju även definitionen i din .h fil som det ser ut, vilket blir i princip samma sak.

Permalänk
Datavetare

Om du vill generalisera din shell-sort till att hantera alla typer som implementerar indikeringsoperatorn [] så behöver du bara ändra tre små ändringar

template<class IndexableContainer> void shellsort(IndexableContainer &a) { int j; const int gap[8]={701, 301, 132, 57, 23, 10, 4, 1}; for(int x = 0; x<8; x++) { for(unsigned int i = gap[x]; i < a.size(); i++) { typename IndexableContainer::value_type tmp = a[i]; for(j=i; j>=gap[x] && tmp < a[j-gap[x]]; j-= gap[x]) { a[j] = a[j-gap[x]]; } a[j] = tmp; } } }

Och vad det gäller shellsort(v) vs shellsort<int>(v), i detta fall spelar det ingen roll (men i detta fall är nog den första att föredra).

Skillnaden är att shellsort(v) låter kompilatorn lura ut dels om man ska använda en template överhuvudtaget (kan ju finns en shellsort(vector<int> &v) funktion som då "vinner") och om det ska använda en template så lurar kompilatorn ut värdet på T vilket i detta fall är möjligt då v är av typen vector<int> då den enda värdet på T som uppfyller sinaturen är int.

I shellsort<int>(v) så specificerar programmaren att T måste vara int, om v då är något annat än vector<int> så blir det ett kompileringsfel.

Edit: Har aldrig använt shell-sort mer än att testat att göra en implementation som kunde köra på flera CPU-kärnor (var relativt lätt just med shell-sort). Att skriva shell-sort för att lära sig är ju definitivt vettigt och jag har full förståelse för sådana experiment. Men finns det någon poäng med att använda denna algoritm i praktiken då den är relativt långsam? Är man nervös över quick-sorts "worst-case" där den konsumerar O(N²) stack och tar O(N²) att köra så finns ju alltid mergesort. Att göra en "in-place" mergesort i C++ är ju relativt enkelt, kan göra t.ex. så här

// Måste ha en bidirektionellt iterator för 'inplace_merge' // Har explicit satt ut 'std::' för att visa att // det är standardfunktioner jag använder template<class BidIt> void mergesort(BidIt first, BidIt last) { typename BidIt::difference_type len = std::distance(first, last); if (len > 1) { BidIt middle = first; std::advance(middle, len / 2); mergesort(first, middle); mergesort(middle, last); std::inplace_merge(first, middle, last); } } // Hjälpfunktion för att ge samma signatur // som du hade i shell-sort template<class Container> void mergesort(Container &a) { mergesort(a.begin(), a.end()); }

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer