Code: Select all
namespace
{
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>
operator+( const vectype<T>& lhs, const vectype<T>& rhs )
{
vectype<T> res;
res.x = lhs.x + rhs.x;
res.y = lhs.y + rhs.y;
if constexpr( num_elements<vectype, T>::value == 3 )
{
res.z = lhs.z + rhs.z;
}
return res;
}
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>
operator+=( vectype<T>& lhs, const vectype<T>& rhs )
{
lhs = lhs + rhs;
return lhs;
}
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>
operator-( const vectype<T>& lhs, const vectype<T>& rhs )
{
vectype<T> res;
res.x = lhs.x - rhs.x;
res.y = lhs.y - rhs.y;
if constexpr( num_elements<vectype, T>::value == 3 )
{
res.z = lhs.z - rhs.z;
}
return res;
}
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>&
operator-=( vectype<T>& lhs, const vectype<T>& rhs )
{
lhs = lhs - rhs;
return lhs;
}
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>
operator*( vectype<T>& lhs, const T rhs )
{
vectype<T> res;
res.x = lhs.x * rhs;
res.y = lhs.y * rhs;
if constexpr( num_elements<vectype, T>::value == 3 )
{
res.z = lhs.z * rhs;
}
return res;
}
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>&
operator*=( vectype<T>& lhs, const T rhs )
{
lhs = lhs * rhs;
return lhs;
}
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>
operator/( vectype<T>& lhs, const T rhs )
{
if constexpr( std::is_floating_point_v<T> )
{
return lhs * ( static_cast< T >( 1 ) / rhs );
}
vectype<T> res;
res.x = lhs.x / rhs;
res.y = lhs.y / rhs;
if constexpr( num_elements<vectype, T>::value == 3 )
{
res.z = lhs.z / rhs;
}
return res;
}
template<template<class> class vectype, class T>
std::enable_if_t<std::is_arithmetic_v<T>, vectype<T>>&
operator/=( vectype<T>& lhs, const T rhs )
{
lhs = lhs / rhs;
return lhs;
}
}
For awhile now I've been trying to figure out std::enable_if to limit the types of variables that can be passed to template functions. I finally got it working for functions that return a value, as you can see above ( if you can read that gibberish ). I can't seems to get it to work when used in the parameter list though. I keep getting the error: "no overloaded function matches the given arguments". I think it's because I get confused about type deduction and replacement of template parameters during type deduction.
For instance:
Code: Select all
namespace String
{
#if defined(UNICODE) || defined(_UNICODE)
using string_type = std::wstring;
using stream_type = std::wstringstream;
using cstring_type = wchar_t*;
#else
using string_type = std::string;
using stream_type = std::stringstream;
using cstring_type = char*;
#endif
template<class T = void> struct is_char_type :std::false_type
{};
template<> struct is_char_type<char> :std::true_type{};
template<> struct is_char_type<wchar_t> : std::true_type{};
template<class T> size_t length( const T* str )
{
static_assert( is_char_type<T>::value, "Function only works with const char * or const wchar_t * types." );
if constexpr( std::is_same_v<T,char> )
{
return strlen( str );
}
else
{
return wcslen( str );
}
}
using cstring = cstring_type;
using string = typename string_type;
using stringstream = typename stream_type;
string encode( const char*str)
{
const auto len = length( str ) + 1;
string res = string( str, str + len );
return res;
}
string encode( const std::string& str )
{
return string( str.begin(), str.end() );
}
string encode( const wchar_t* str )
{
const auto len = length( str ) + 1;
string res = string( str, str + len );
return res;
}
string encode( const std::wstring& str )
{
return string( str.begin(), str.end() );
}
}
I would have thought this would work:
Code: Select all
template<class T> size_t length(
const std::enable_if_t<typename is_char_type<T>::type, T>* str )
{
if constexpr( std::is_same_v<T,char> )
{
return strlen( str );
}
else
{
return wcslen( str );
}
}
Code: Select all
template<class T>
std::enable_if_t<typename is_char_type<T>::type, size_t> length( const T* str )
{
if constexpr( std::is_same_v<T,char> )
{
return strlen( str );
}
else
{
return wcslen( str );
}
}