Newsgroup: it.comp.lang.c++
Titolo: Come semplificare questa scrittura?

Come potete vedere, in main() utilizzo la scrittura
"function<float (float)> func(&f);"
dove f è di tipo float (float).
Mi piacerebbe si potesse scrivere anche soltanto
"function func(&f);".
Per il caso in cui f è una struttura con operator() la vedo difficile, 
ma pazienza.
Ricordate che cerco una scrittura /complessivamente/ più semplice!
E' inutile togliere <float (float)> da una parte se poi devo scriverlo 
da un'altra :)
======
#include <memory>
using namespace std;
template <class T>
class function;
template <class T, class U>
class function<T (U)>
{
private:
	struct impl
	{
		virtual ~impl() {}
		virtual impl* clone() const = 0;
		virtual T operator()(U) const = 0;
	};
	template <class F>
	struct wrapper : impl
	{
		explicit wrapper(F const& f)
			: f(f) {}
		impl* clone() const
		{
			return new wrapper<F>(this->f);
		}
		T operator()(U x) const
		{
			return f(x);
		}
	private:
		mutable F f;
	};
public:
	template <class F>
	function(F const& f)
		: pimpl(new wrapper<F>(f)) {}
	function(function const& rhs)
		: pimpl(rhs.pimpl->clone()) {}
	function& operator=(function const& rhs)
	{
		this->pimpl.reset(rhs.pimpl->clone());
		return *this;
	}
	T operator()(U x) const
	{
		return (*this->pimpl)(x);
	}
private:
	std::auto_ptr<impl> pimpl;
};
float f(float x)
{
	return x;
}
class G
{
public:
	float operator()(float x)/* const*/ { return x; }
};
int main()
{
	function<float (float)> func(&f);
	float x = func(1);
	x += 1;
	G g;
	function<float (float)> gunc(g);
}
======
Kiuhnm

 }
Cosi' non e' abbastanza semplice?
int main() {
     typedef function<float (float)> myfunction;
     myfunction func(&f);
     float x = func(1);
     x += 1;
     G g;
     myfunction gunc(g);
}
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

Carlo Milanesi ha scritto:

Ho anche scritto:
"E' inutile togliere <float (float)> da una parte se poi devo scriverlo 
da un'altra :)"
Il punto non era la ripetizione tra i due utilizzi di func.
Kiuhnm

>> }
Se ho ben capito, vorresti dedurre il tipo del template dal tipo 
dell'inizializzatore; per esempio, trasformando il seguente codice:
     std::vector<int> v;
     std::vector<int>::iterator vi = v.begin();
nel seguente:
     std::vector<int> v;
     std::vector::iterator vi = v.begin();
Ebbene, non mi sembra possibile nel linguaggio C++ attuale, ma il 
comitato di standardizzazione sta vagliando un'estensione al linguaggio 
di questo tipo:
Apri 
http://www.artima.com/cppsource/cpp0xP.html
 e cerca "auto".


 Apri 
http://www.artima.com/cppsource/cpp0xP.html
 e cerca "auto".
Questa è una forma di type inference. Comodo, ma ortogonale a quello che 
chiedo io.
Spero che "auto" riesca a fare, in tutto e per tutto, le veci di "typeof".
Kiuhnm

 A<int> c;
...nel qual caso anche questa e' valida. Altrimenti l'unica speranza e'
poter separare interfaccia da implementazione, dove solo
l'implementazione dipende dal/gli parametro/i del template. In questo
caso e' possibile avere una classe che delega l'implementazione verso
una classe template attraverso una classe base astratta comune a tutte
le istanze del template. La classe delegante ha uno o piu' costruttori
template che usano l'inferenza sui tipi dei propri argomenti per
scegliere la specializzazione della classe delegata da istanziare.
Se questa strada ti interessa posto un esempio.
Ciao,
Nicola

 Se questa strada ti interessa posto un esempio.
Un esempio c'è già nel primo post di questo thread.
Questa tecnica viene solitamente chiamata "Type Erasure", ma non è priva 
di problemi.
struct Base
{
	virtual ~Base() {};
	virtual void* get() = 0;
};
template <class T>
class Spec : public Base
{
	T t;
	Spec();
public:
	Spec(T t) : t(t) {}
	virtual void* get() { return &t; }
};
class A
{
	Base &b;
	A& operator=(A&);		// ...
public:
	template <class T>
	A(T t) : b(*new Spec<T>(t)) {}
	~A() { delete &b; }
	template <class T>
	void get(T& t)
	{
#ifdef _DEBUG
		if (!dynamic_cast< typename Spec<T>* >(&b))		// Runtime: awful
			throw;
#endif
		t = *static_cast<T*>(b.get());
	}
};
int main()
{
	A a(5);
	int n;
	a.get(n);
	if (n != 5)
		throw;
//	double d;
//	a.get(d);		// errore!
}
Kiuhnm