1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
#include <iostream>
#include <type_traits>
template < typename T >
class v3 {
T x {};
T y {};
T z {};
public:
v3() = default ;
v3( const T& a, const T& b, const T& c ) : x(a), y(b), z(c) {}
// ...
// http://en.cppreference.com/w/cpp/types/is_arithmetic
// http://en.cppreference.com/w/cpp/types/conditional
// http://en.cppreference.com/w/cpp/types/integral_constant
template < typename A, typename B > // true if both A and B are arithmetic types
struct are_arithmetic : std::conditional< std::is_arithmetic<A>::value &&
std::is_arithmetic<B>::value,
std::true_type, std::false_type >::type {};
// v3<T> *= arithmetic_type
// http://en.cppreference.com/w/cpp/types/enable_if
template < typename U > // enable only if both T and U are arithmetic types
typename std::enable_if< are_arithmetic<T,U>::value, v3<T>& >::type
operator *= ( U value ) { x *= value ; y *= value ; z *= value ; return *this ; }
// v3<T> * arithmetic_type
template < typename U > friend // enable only if both T and U are arithmetic types
typename std::enable_if< are_arithmetic<T,U>::value, v3<T> >::type
operator * ( v3<T> vec, U value ) { return vec *= value ; }
// arithmetic_type * v3<T>
template < typename U > friend // enable only if both T and U are arithmetic types
typename std::enable_if< are_arithmetic<T,U>::value, v3<T> >::type
operator * ( U value, v3<T> vec ) { return vec *= value ; }
// likewise for operator /
friend std::ostream& operator<< ( std::ostream& stm, const v3<T>& vec )
{ return stm << "{ " << vec.x << ", " << vec.y << ", " << vec.z << " }" ; }
};
int main()
{
v3<double> vec { 12.34, 23.45, 34.56 } ;
std::cout << vec << '\n' ;
vec *= 1.2 ;
std::cout << vec << '\n' ;
std::cout << vec*2 << '\n' << 3*vec << '\n' ;
// vec * "hello" ; // *** error: invalid operands, no match for operator *
}
|