Coerce.h
// Coerce.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022
#pragma once
#ifndef Ceda_cxUtils_Coerce_H
#define Ceda_cxUtils_Coerce_H
#include "cxUtils.h"
#include "Detect.h"
#include "MathExt.h"
namespace ceda
{
template<typename T1, typename T2> struct is_subtype_as_subset : std::false_type {};
template<typename T> struct is_subtype_as_subset<T,T> : std::true_type {};
template<> struct is_subtype_as_subset<int8,int16> : std::true_type {};
template<> struct is_subtype_as_subset<int8,int32> : std::true_type {};
template<> struct is_subtype_as_subset<int8,int64> : std::true_type {};
template<> struct is_subtype_as_subset<int16,int32> : std::true_type {};
template<> struct is_subtype_as_subset<int16,int64> : std::true_type {};
template<> struct is_subtype_as_subset<int32,int64> : std::true_type {};
template<> struct is_subtype_as_subset<uint8,uint16> : std::true_type {};
template<> struct is_subtype_as_subset<uint8,uint32> : std::true_type {};
template<> struct is_subtype_as_subset<uint8,uint64> : std::true_type {};
template<> struct is_subtype_as_subset<uint16,uint32> : std::true_type {};
template<> struct is_subtype_as_subset<uint16,uint64> : std::true_type {};
template<> struct is_subtype_as_subset<uint32,uint64> : std::true_type {};
template<> struct is_subtype_as_subset<int8,float32> : std::true_type {};
template<> struct is_subtype_as_subset<int16,float32> : std::true_type {};
template<> struct is_subtype_as_subset<uint8,float32> : std::true_type {};
template<> struct is_subtype_as_subset<uint16,float32> : std::true_type {};
template<> struct is_subtype_as_subset<int8,float64> : std::true_type {};
template<> struct is_subtype_as_subset<int16,float64> : std::true_type {};
template<> struct is_subtype_as_subset<int32,float64> : std::true_type {};
template<> struct is_subtype_as_subset<uint8,float64> : std::true_type {};
template<> struct is_subtype_as_subset<uint16,float64> : std::true_type {};
template<> struct is_subtype_as_subset<uint32,float64> : std::true_type {};
template<> struct is_subtype_as_subset<float32,float64> : std::true_type {};
/*
template<typename T1, typename T2> bool equal_values(const T1& t1, const T2& t2)
{
// bool, char, char8_t char16_t, char32_t, wchar_t, short, int, long, long long
if constexpr( std::is_integral<T1>::value && std::is_integral<T2>::value )
return (long long) t1 == (long long) t2;
else
return t1 == t2;
}
*/
// assign a from b
template<typename To, typename From>
bool coerce(To& a, const From& b, bool allowExplicitConversions)
{
if constexpr (is_subtype_as_subset<From,To>::value)
{
a = b;
return true;
}
else if constexpr (has_implicit_cast<To,From>::value)
{
// C++ allows for implicit conversions which are lossy and produce warnings, so we use a static cast to silence the warnings
a = static_cast<To>(b);
if constexpr(std::is_arithmetic<To>::value && std::is_arithmetic<From>::value)
{
return allowExplicitConversions || IsNumericallyEqual(a,b);
}
else
{
return allowExplicitConversions || a==b;
}
}
else if constexpr (has_static_cast_t<To,From>::value)
{
if (allowExplicitConversions)
{
a = static_cast<To>(b);
}
}
return false;
}
} // namespace ceda
#endif // include guard