Strona 1 z 1
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 18:15
autor: diego_maradona
Utworzyłem szablon funkcji która zamienia dwie zmienne.
Kod: Zaznacz cały
#include "stdafx.h"
#include <iostream>
using namespace std;
template <class Type>
void swap(Type& firstVariable, Type& secondVariable)
{
Type temp;
temp = firstVariable;
firstVariable = secondVariable;
secondVariable = temp;
}
int main()
{
int a,b;
a=2;
b=3;
swap(a,b);
cout<<b;
cout<<a;
cout<<endl;
system("PAUSE");
return 0;
}
Po kompilowaniu wychodzi błąd
1>------ Build started: Project: swapFile, Configuration: Debug Win32 ------
1> swapFile.cpp
1>swapFile.cpp(24): error C2668: 'swap' : ambiguous call to overloaded function
1> swapFile.cpp(9): could be 'void swap<int>(Type &,Type &)'
1> with
1> [
1> Type=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\utility(100): or 'void std::swap<std::ios_base::iostate>(_Ty &,_Ty &)'
1> with
1> [
1> _Ty=std::ios_base::iostate
1> ]
1> while trying to match the argument list '(int, int)'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Nie rozumiem gdzie ta dwuznaczność, kod praktycznie przepisany z książki...
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 18:22
autor: argv
Stąd:
Kod: Zaznacz cały
http://www.cplusplus.com/reference/algorithm/swap/
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 18:41
autor: diego_maradona
rozumiem, że keyword "swap" jest zawarty w którejś z 2 bibliotek które zawarłem? Zamieniłem na "exchange" i teraz wszystko działa
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 19:29
autor: abc666
diego_maradona, skoro jest to po co pisać tą funkcję ?
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 20:08
autor: Afish
Zapewne aby się nauczyć. Wbrew pozorom przy swapie można się nieźle zabawić. Na przykład można próbować napisać swapa nie wykorzystującego pomocniczej zmiennej. Warto też się zastanowić, czy swapując dwa wskaźniki chcemy zamienić miejsca w pamięci, na które te wskaźniki wskazują, czy chcemy zamienić wartości. Taka prosta funkcja, a ile radości.
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 20:13
autor: abc666
Na przykład można próbować napisać swapa nie wykorzystującego pomocniczej zmiennej
Próbować można
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 20:19
autor: Afish
Brzmi, jakbyś nie wierzył, że jest to możliwe. Osobiście znam dwa rozwiązania, ale zapewne jest więcej

[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 21:13
autor: abc666
Dla dowolnych obiektów?
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 21:20
autor: Afish
Dla liczb całkowitych. Ale ponieważ wykorzystuje to operacje na bitach, więc poprzez niemiłe rzutowania zadziałałoby też dla obiektów.
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 21:27
autor: abc666
No na liczbach to ok, ale w ogólności nie widzę na to szans.
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 21:52
autor: Afish
Kod: Zaznacz cały
#include <cstdio>
#include <cstdlib>
template <typename T> void change(T& a, T& b){
for(int i=0;i<sizeof(T);i+=4){
int* c = reinterpret_cast<int*>(&a) + i/4;
int* d = reinterpret_cast<int*>(&b) + i/4;
*c ^= *d;
*d ^= *c;
*c ^= *d;
}
}
class Test1{
public:
int x;
double z;
Test1(int X, double Z) : x(X), z(Z) {}
};
class Test2{
public:
int* tab;
int val;
int size;
Test2(int Size, int Val) : size(Size), val(Val){
tab = new int[size];
for(int i=0;i<size;++i){
tab[i] = val;
}
}
~Test2(){
delete[] tab;
}
void print(){
for(int i=0;i<size;++i){
printf("%d ",tab[i]);
}
}
};
int main(){
int a = 5;
int b = 8;
change(a,b);
printf("%d %d
", a, b);
double c = 3.14;
double d = 5.24;
change(c,d);
printf("%lf %lf
",c,d);
Test1 e(5,23.0);
Test1 f(7,14.0);
change(e,f);
printf("%d %lf %d %lf
",e.x,e.z,f.x,f.z);
Test2 g(3,35);
Test2 h(4,1);
change(g,h);
g.print();
h.print();
return EXIT_SUCCESS;
}
VS 2008 nie sprawia problemów. Ale ponieważ chcemy zrobić to bez żadnej zmiennej pomocniczej, więc musimy trochę przerobić naszą funkcję: zamieniamy ją na rekurencję ogonową, która dzięki optymalizacji kompilatora zostanie rozwinięta, a dodatkowa optymalizacja zamieni wskaźniki na bezpośrednie odwołania do pamięci, czego efektem będzie brak zmiennych pomocniczych. Zapewne da się też pobawić szablonami rekurencyjnymi, aby uzyskać podobny efekt, a wtedy nie będą potrzebne optymalizacje, gdyż wszystko będzie po prostu w kodzie.
PS W sumie zamiast na sztywno wpisywać 4 powinienem użyć sizeof(int).
[C++][Visual studio 2010] szablony funkcji swap
: 18 wrz 2011, o 22:15
autor: abc666
Hmm to już trochę pytanie filozoficzne czy wtedy nie używamy zmiennej pomocniczej? Czy zmienna pomocnicza istnieje tylko wtedy kiedy zawrzemy ją jawnie w kodzie?
[C++][Visual studio 2010] szablony funkcji swap
: 19 wrz 2011, o 08:37
autor: Afish
A to już od kompilatora wszystko zależy. Czasami poprzez optymalizacje jawnie zadeklarowane zmienne są usuwane, czasami dodatkowe zmienne są tworzone, aby przekazać jakieś dane. Ja w swoim swapie chciałem pokazać, że da się zamienić wartości dwóch zmiennych nie tworząc jawnie kopii którejś z nich. Ale rzeczywiście w moim przykładzie trzeba się nakombinować i liczyć na pomoc kompilatora, więc nie jest to do końca zgodne z regułami.