/******************************************************************************
Online C++ Compiler.
Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <cstdint> // for std::uint32_t
#include <type_traits> // for is_same
#include <iostream> // for cout
using tU32 = std::uint32_t ;
template <typename... Types>
struct EnumTypeRegister
{
constexpr EnumTypeRegister() {}
};
template <typename QueriedType, typename Type>
constexpr tU32 GetEnumPosition(EnumTypeRegister<Type>)
{
static_assert(std::is_same<Type, QueriedType>::value,
"Unable to get index for type missing in TypeRegister");
return tU32(0U) ;
}
template <typename QueriedType, typename Type, typename... Types>
constexpr std::enable_if_t<std::is_same<Type, QueriedType>::value, tU32>
GetEnumPosition(EnumTypeRegister<Type, Types...>)
{
return 0U ;
}
template <typename QueriedType, typename Type, typename... Types>
constexpr std::enable_if_t<!std::is_same<Type, QueriedType>::value, tU32>
GetEnumPosition(EnumTypeRegister<Type, Types...>)
{
return 1U + GetEnumPosition<QueriedType>(EnumTypeRegister<Types...>()) ;
}
//for C++17
//template <typename QueriedType, typename Type, typename... Types>
//constexpr tU32 GetEnumPosition(EnumTypeRegister<Type, Types...>)
//{
// if constexpr (std::is_same<Type, QueriedType>::value)
// {
// return 0U ;
// } else
// {
// return 1U + GetEnumPosition<QueriedType>(EnumTypeRegister<Types...>()) ;
// }
//}
//
//*************** Add new enumaration here ************************************
enum class Cpu_Error
{
Ok,
Alu,
Rom,
Ram
} ;
enum class Measure_Error
{
OutOfLimits,
Ok,
BadCode
} ;
enum class My_Error
{
Error1,
Error2,
Error3,
Error4,
Ok
} ;
// Add enum in the category
using CategoryErrorsList = EnumTypeRegister<Cpu_Error, Measure_Error, My_Error>;
//*************** !Add new enumaration here ************************************
template<typename T>
constexpr tU32 GetCategory(const T)
{
constexpr CategoryErrorsList categoryErrorsList;
return static_cast<tU32>(GetEnumPosition<T>(categoryErrorsList));
}
template<typename T>
constexpr tU32 GetOk(const T)
{
return static_cast<tU32>(T::Ok);
}
class ReturnCode
{
public:
ReturnCode()
{
}
template<class T>
explicit ReturnCode(const T initReturnCode):
errorValue(static_cast<tU32>(initReturnCode)),
errorCategory(GetCategory(initReturnCode)),
goodCode(GetOk(initReturnCode))
{
static_assert(std::is_enum<T>::value, "The type is not enum") ;
}
template<class T>
operator T() const
{
//Cast to only enum types
static_assert(std::is_enum<T>::value, "The type is not enum") ;
return static_cast<T>(errorValue) ;
}
tU32 GetValue() const
{
return errorValue;
}
tU32 GetCategoryValue() const
{
return errorCategory;
}
operator bool() const
{
return (GetValue() != goodCode);
}
template<class T>
ReturnCode& operator=(const T returnCode)
{
errorValue = static_cast<tU32>(returnCode) ;
errorCategory = GetCategory(returnCode) ;
goodCode = GetOk(returnCode) ;
return *this ;
}
private:
tU32 errorValue = 0U ;
tU32 errorCategory = 0U ;
tU32 goodCode = 0U ;
} ;
Cpu_Error CpuCheck()
{
return Cpu_Error::Ram;
}
My_Error MyCheck()
{
return My_Error::Error4;
}
int main()
{
ReturnCode result(CpuCheck());
std::cout << "Return code: "<< result.GetValue() << " Return category: "<< result.GetCategoryValue() << std::endl;
if (result) //if something wrong
{
result = MyCheck() ;
std::cout << "Return code: "<< result.GetValue() << " Return category: "<< result.GetCategoryValue() << std::endl;
}
result = Measure_Error::BadCode ;
std::cout << "Return code: "<< result.GetValue() << " Return category: "<< result.GetCategoryValue() << std::endl;
result = Measure_Error::Ok ;
if (!result) //if all is Ok
{
Measure_Error mError = result ;
if (mError == Measure_Error::Ok)
{
std::cout << "mError: "<< tU32(mError) << std::endl;
}
}
return 0;
}