#include <iostream>
namespace NS_A{
template<typename T>
class ClassA{
public :
T num;
ClassA(T n = 0) : num(n) {}
ClassA(const ClassA& other) : num(other.num) {}
~ClassA(){};
ClassA& operator=(const ClassA& rhs){num=rhs.num;return *this;}
ClassA& operator=(const T& rhs){num=rhs;return *this;}
ClassA& operator *= (const ClassA& rhs){num=num * rhs.num;return *this;}
friend ClassA<T> operator * (const ClassA<T>& lhs, const ClassA<T>& rhs){ClassA<T> t=lhs;t *= rhs;return t;}
friend std::ostream& operator << (std::ostream& os, const ClassA<T>& arg){return os << arg.num;}
friend T get_tripled(const ClassA<T>& arg){return arg.num*3;} // ClassA作者が用意している
};
}
namespace NS_B{
template<typename T>
class ClassB{
public :
T num;
ClassB(T n = 0) : num(n) {}
ClassB(const ClassB& other) : num(other.num) {}
~ClassB(){};
ClassB& operator=(const ClassB& rhs){num=rhs.num;return *this;}
ClassB& operator=(const T& rhs){num=rhs;return *this;}
ClassB& operator += (const ClassB& rhs){num=num + rhs.num;return *this;}
friend ClassB<T> operator + (const ClassB<T>& lhs, const ClassB<T>& rhs){ClassB<T> t=lhs;t += rhs;return t;}
friend std::ostream& operator << (std::ostream& os, const ClassB<T>& arg){return os << arg.num;}
// friend T get_tripled(const ClassB<T>& arg){return arg.num*3;} // ClassB作者が用意していない
};
}
namespace NS_C{
template<typename T>
inline T get_tripled(const T& arg){
std::cout << "以下、自前のget_tripledが用意されていませんでした。" << std::endl;
return arg+arg+arg; // 例えばClassBではこちらが選ばれる
}
}
int main()
{
NS_A::ClassA<double> a=20;
NS_B::ClassB<int> b=30;
using NS_C::get_tripled;
std::cout << "a : " << get_tripled(a) << std::endl;
std::cout << "b : " << get_tripled(b) << std::endl;
return 0;
}