Click on templates.cpp to get source.
#include <iostream>
#include <typeinfo>
using namespace std;
template <class T>
class A
{public: T x;
A(T y) : x(y) {}
typedef T elemT;
};
template class A<int>; // explicit template expansion
// is often useful to speed compilation
template <> // template specialization
class A<float>
{public: float z; // new data member
float x;
A(float y) : z(y+10.0), x(y) {}
};
template< template<class> class C >
// template-template parameters
class B
{public:
C<int> ci;
C<float> cf;
B(int a, float b) : ci(a), cf(b) {}
};
template<class T> // template function: overloaded <<
ostream& operator<<(ostream& out, const A<T>& a)
{out << "An A<" << typeid(T).name() << ">: x member: " << a.x;
return out; }
template<> // template function: overloaded << specialized for A<float>
ostream& operator<<(ostream& out, const A<float>& a)
{out << "Specialized <<: an A<float>: x member: " << a.x << ", z member: " << a.z;
return out;
}
#ifdef FWDDCL
class A<double>; // forward declare template specialization
// NOTE: must have template specialization later; is *not* template expansion
// try g++ -Wall -std=c++23 templates.cpp -DFWDDCL
// to trigger "error: variable ‘A<double> d’ has initializer but incomplete type"
// at variable declaration
#endif
#ifdef DOUBLE
// compile as g++ -Wall -std=c++23 templates.cpp -DDOUBLE
// or g++ -Wall -std=c++23 templates.cpp -DDOUBLE -DFWDDCL
template <> // template specialization
class A<double>
{public: double z; // new data member
double x;
A(double y=0.0) : z(y+10.0), x(y)
{cout << "created an A<double> with z=" << z << endl;}
};
#endif
int main(void)
{A<int> a1(5);
cout << endl << "A<int> a1(5); cout << a1: " << a1 << endl << endl;
A<char> a2('A'); // implicit template expansion with char type
cout << "A<char> a2('A'); cout << a2: " << a2 << endl << endl;
A<float> a3(1.5f);
cout << "A<float> a3(1.5f); cout << a3: " << a3 << endl << endl;
B<A> b(5, 1.5);
cout << "B<A> b(5, 1.5); cout << b.ci: " << b.ci
<< endl << " cout << b.cf: " << b.cf
<< endl << " cout << b.cf.z: " << b.cf.z
<< endl << endl;
#ifdef SPECDOUB
class A<double>; // declaring template specialization
// triggers compilation error:
// "specialization of ‘template<class T> class A’ must appear at namespace scope"
// if template specialization not present
// try g++ -Wall -std=c++23 templates.cpp -DSPECDOUB to trigger error
// compiles with g++ -Wall -std=c++23 templates.cpp -DDOUBLE -DSPECDOUB
#endif
A<double> d(3.14159);
cout << "A<double> d(3.14159); cout << d: " << d << endl << endl;
}//main