Skip to content

Instantly share code, notes, and snippets.

@B1Z0N
Created July 24, 2019 00:39
Show Gist options
  • Save B1Z0N/92e6787407e04fb5b7440dcd39f57345 to your computer and use it in GitHub Desktop.
Save B1Z0N/92e6787407e04fb5b7440dcd39f57345 to your computer and use it in GitHub Desktop.
c++ template traits implemented for better understanding
#include <utility>
//*********************TRANSFORMATION*TRAITS***************************
// Remove reference
template <typename T>
struct RemoveReferenceT
{
using type = T;
};
template <typename T>
struct RemoveReferenceT<T&>
{
using type = T;
};
template <typename T>
struct RemoveReferenceT < T&& >
{
using type = T;
};
template <typename T>
using RemoveReference = typename RemoveReferenceT<T>::type;
// Add lvalue reference
template <typename T>
struct AddLValueReferenceT {
using type = T&;
};
template <>
struct AddLValueReferenceT<void> {
using type = void;
};
template <>
struct AddLValueReferenceT<const void> {
using type = void const;
};
template <>
struct AddLValueReferenceT<void volatile> {
using type = void volatile;
};
template <>
struct AddLValueReferenceT<const void volatile> {
using type = void const volatile;
};
template <typename T>
using AddLValueReference = typename AddLValueReferenceT<T>::type;
// Add rvalue reference
template <typename T>
struct AddRValueReferenceT {
using type = T &&;
};
template <>
struct AddRValueReferenceT<void> {
using type = void;
};
template <>
struct AddRValueReferenceT<const void> {
using type = void const;
};
template <>
struct AddRValueReferenceT<void volatile> {
using type = void volatile;
};
template <>
struct AddRValueReferenceT<const void volatile> {
using type = void const volatile;
};
template <typename T>
using AddRValueReference = typename AddRValueReferenceT<T>::type;
// Remove const
template <typename T>
struct RemoveConstT
{
using type = T;
};
template <typename T>
struct RemoveConstT<const T>
{
using type = T;
};
template <typename T>
using RemoveConst = typename RemoveConstT<T>::type;
// Add const not neede, we can use const T for any T
// Remove volatile
template <typename T>
struct RemoveVolatileT
{
using type = T;
};
template <typename T>
struct RemoveVolatileT<volatile T>
{
using type = T;
};
template <typename T>
using RemoveVolatile = typename RemoveVolatileT<T>::type;
// Remove CV
template <typename T>
struct RemoveCVT : RemoveConstT<RemoveVolatile<T>> { };
template <typename T>
using RemoveCV = typename RemoveCVT<T>::type;
// Decay
template <typename T>
struct DecayT : RemoveCVT<T> { };
template <typename T>
struct DecayT<T[]>
{
using type = T*;
};
template <typename T, std::size_t N>
struct DecayT<T[N]>
{
using type = T*;
};
template <typename R, typename... Args>
struct DecayT<R( Args... )>
{
using type = R (*) ( Args... );
};
/**
* Specialization for C-style varargs
*/
template<typename R, typename... Args>
struct DecayT<R( Args..., ... )>
{
using type = R (*)(Args..., ...);
};
template <typename T>
using Decay = typename DecayT<T>::type;
//*********************PREDICATE*TRAITS***************************
// Utility true and false types
template <bool val>
struct BoolConstant
{
using type = BoolConstant<val>;
static constexpr bool value = val;
};
using Falsetype = BoolConstant<false>;
using Truetype = BoolConstant<true>;
// Is same type?
template <typename T1, typename T2>
struct IsSameT : Falsetype { };
template <typename T>
struct IsSameT<T, T> : Truetype { };
template <typename T1, typename T2>
constexpr bool IsSame = IsSameT<T1, T2>::value;
//*********************PREDICATE*TRAITS***************************
// PlusResult
template <typename T1, typename T2>
struct PlusResultT
{
using type = decltype( std::declval<T1>() + std::declval<T2>() );
};
template <typename T1, typename T2>
using PlusResult = typename PlusResultT<T1, T2>::type;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment