Newsgroup: it.comp.lang.c++
Titolo: Es. su template. (Ho dimenticato qualcosa?)

Es:
 >>>>>>>>>>>>>>
Write a ternary metafunction replace_type<c,x,y> that takes an arbitrary 
compound type c as its first parameter, and replaces all occurrences of 
a type x within c with y:
     typedef replace_type< void*, void, int >::type t1; // int*
     typedef replace_type<
         int const*[10]
       , int const
       , long
     >::type t2; // long* [10]
     typedef replace_type<
         char& (*)(char&)
       , char&
       , long&
     >::type t3; // long& (*)(long&)
You can limit the function types you operate on to those with fewer than 
two arguments.
<<<<<<<<<<<<<<
Sono agli inizi quindi potrei avere fatto qualche errore o aver 
dimenticato qualcosa.
La struttura add_const_ref fa parte di un "esercizio" precedente.
 >>>>>>>>>>>>>>
#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>
//#include <iostream>
using namespace boost;		// solo perché è una prova
template <typename T>
struct add_const_ref
{
	typedef typename add_reference< typename add_const<T>::type >::type type;
};
template <typename C, typename X, typename Y>
struct replace_type { typedef C type; };
template <typename X, typename Y>
struct replace_type<X, X, Y> { typedef Y type; };
template <typename X, typename Y>
struct replace_type<X*, X*, Y> { typedef Y type; };
template <typename X, typename Y>
struct replace_type<X&, X&, Y> { typedef Y type; };
template <typename C, typename X, typename Y>
struct replace_type<C*, X, Y>
{
	typedef typename replace_type< C, X, Y >::type* type;
};
template <typename C, typename X, typename Y>
struct replace_type<C[], X, Y>
{
	typedef typename replace_type< C, X, Y >::type type[];
};
template <typename C, unsigned N, typename X, typename Y>
struct replace_type<C[N], X, Y>
{
	typedef typename replace_type< C, X, Y >::type type[N];
};
template <typename C, typename X, typename Y>
struct replace_type<C&, X, Y>
{
	typedef typename replace_type< C, X, Y >::type& type;
};
template <typename C, typename X, typename Y>
struct replace_type<C const, X, Y>
{
	typedef typename replace_type< C, X, Y >::type const type;
};
// Questa istanza elimina un'ambiguità tra <C const,X,Y> e <X,X,Y> 
quando si ha <const,const,.>.
// L'ambiguità sembra sorgere solo con "const" e "volatile".
template <typename C, typename Y>
struct replace_type<C const, C const, Y> { typedef Y type; };
template <typename C, typename X, typename Y>
struct replace_type<C volatile, X, Y>
{
	typedef typename replace_type< C, X, Y >::type volatile type;
};
// Questa istanza elimina un'ambiguità tra <C volatile,X,Y> e <X,X,Y> 
quando si ha <volatile,volatile,.>.
// L'ambiguità sembra sorgere solo con "const" e "volatile".
template <typename C, typename Y>
struct replace_type<C volatile, C volatile, Y> { typedef Y type; };
template <typename C, typename S, typename X, typename Y>
struct replace_type<C S::*, X, Y>		// NOTA: non esiste un "reference to 
member" in C++!
{
	typedef typename replace_type< C, X, Y >::type S::* type;
};
template <typename R, typename P, typename X, typename Y>
struct replace_type<R (*)(P), X, Y>		// NOTA: non esiste un "reference 
to member" in C++!
{
	typedef typename replace_type< R, X, Y >::type (*type)(typename 
replace_type< P, X, Y >::type);
};
template <typename R, typename S, typename P, typename X, typename Y>
struct replace_type<R (S::*)(P), X, Y>		// NOTA: non esiste un 
"reference to member" in C++!
{
	typedef typename replace_type< R, X, Y >::type (S::*type)(typename 
replace_type< P, X, Y >::type);
};
struct A { int f[5]; };
int main()
{
	const bool r
		=	is_same< add_const_ref<int>::type, int const& >::value
		&&	is_same< add_const_ref<char>::type, char const& >::value
		&&	is_same< add_const_ref<long&>::type, long& >::value;
	BOOST_STATIC_ASSERT(r);
	const bool r2
		=	is_same< replace_type<int const*[10], int const, long>::type, 
long*[10]>::value
		&&	is_same< replace_type<int volatile, int volatile, long>::type, 
long>::value
		&&	is_same< replace_type<int const&, int, char>::type, char const&>::value
		&&	is_same< replace_type<int*&, int*&, char>::type, char>::value
		&&	is_same< replace_type<int*&, int*, char>::type, char&>::value
		&&	is_same< replace_type<int*&, int, char>::type, char*&>::value
		&&	is_same< replace_type<int*****&, int***, char>::type, char**&>::value
		&&	is_same< replace_type<int*&, int&, char>::type, int*&>::value
		&&	is_same< replace_type<int[], int, char>::type, char[]>::value
		&&	is_same< replace_type<int[0], int, char>::type, char[0]>::value
		&&	is_same< replace_type<int[10][2], int, char>::type, char[10][2]>::value
		&&	is_same< replace_type< char& (*)(char*&), char, int >::type, int& 
(*)(int*&) >::value
		&&	is_same< replace_type< char& (*)(char&), char&, long& >::type, 
long& (*)(long&) >::value
		&&	is_same< replace_type< char& (A::*)(char*&), char, int >::type, 
int& (A::*)(int*&) >::value
		&&	is_same< replace_type<int A::*, int, char>::type, char A::*>::value
		&&	is_same< replace_type<int (A::*)[], int, char>::type, char 
(A::*)[]>::value
		&&	is_same< replace_type<int (A::*)[10][12], int, char>::type, char 
(A::*)[10][12]>::value;
	BOOST_STATIC_ASSERT(r2);
}
<<<<<<<<<<<<<<
Kiuhnm

Kiuhnm ha scritto:
[...]
Ora che ci penso, ho dimenticato le funzioni senza parametri.
Kiuhnm