[C++][Visual studio 2010] szablony funkcji swap

diego_maradona
Użytkownik
Użytkownik
Posty: 184
Rejestracja: 16 cze 2010, o 00:59
Płeć: Mężczyzna
Lokalizacja: Kraków
Podziękował: 80 razy

[C++][Visual studio 2010] szablony funkcji swap

Post 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...
Ostatnio zmieniony 18 wrz 2011, o 20:21 przez Afish, łącznie zmieniany 1 raz.
Powód: Delikatna korekta nazwy tematu.
Awatar użytkownika
argv
Użytkownik
Użytkownik
Posty: 569
Rejestracja: 27 maja 2009, o 01:27
Płeć: Mężczyzna
Podziękował: 51 razy
Pomógł: 66 razy

[C++][Visual studio 2010] szablony funkcji swap

Post autor: argv »

Stąd:

Kod: Zaznacz cały

http://www.cplusplus.com/reference/algorithm/swap/
diego_maradona
Użytkownik
Użytkownik
Posty: 184
Rejestracja: 16 cze 2010, o 00:59
Płeć: Mężczyzna
Lokalizacja: Kraków
Podziękował: 80 razy

[C++][Visual studio 2010] szablony funkcji swap

Post 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
abc666

[C++][Visual studio 2010] szablony funkcji swap

Post autor: abc666 »

diego_maradona, skoro jest to po co pisać tą funkcję ?
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++][Visual studio 2010] szablony funkcji swap

Post 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.
abc666

[C++][Visual studio 2010] szablony funkcji swap

Post autor: abc666 »

Na przykład można próbować napisać swapa nie wykorzystującego pomocniczej zmiennej
Próbować można
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++][Visual studio 2010] szablony funkcji swap

Post autor: Afish »

Brzmi, jakbyś nie wierzył, że jest to możliwe. Osobiście znam dwa rozwiązania, ale zapewne jest więcej :)
abc666

[C++][Visual studio 2010] szablony funkcji swap

Post autor: abc666 »

Dla dowolnych obiektów?
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++][Visual studio 2010] szablony funkcji swap

Post 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.
abc666

[C++][Visual studio 2010] szablony funkcji swap

Post autor: abc666 »

No na liczbach to ok, ale w ogólności nie widzę na to szans.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++][Visual studio 2010] szablony funkcji swap

Post 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).
abc666

[C++][Visual studio 2010] szablony funkcji swap

Post 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?
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++][Visual studio 2010] szablony funkcji swap

Post 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.
ODPOWIEDZ