#include <cstddef>
#include <cstdint>
#include <type_traits>
// bool val. to bool type
template <const bool Bool>
struct BoolType {};
template<>
struct BoolType<true> {
typedef std::true_type Type;
};
template<>
struct BoolType<false> {
typedef std::false_type Type;
};
#define BOOL_TYPE(BoolVal) BoolType<BoolVal>::Type
// std::is_fundamental [http://w...content-available-to-author-only...s.com/reference/type_traits/is_fundamental/]
enum class ECFundamentalTypeTags {
UNIDENTIFIED,
BOOL,
SIGNED_CHAR,
UNSIGNED_CHAR,
// Signedness of wchar_t is unspecified
// [http://stackoverflow.com/questions/11953363/wchar-t-is-unsigned-or-signed]
WCHAR,
//// 'char16_t' AND 'char32_t' SHOULD be a keywords since the C++11,
//// BUT MS VS Community 2013 Upd 5 does NOT supports that
//// AND specifys 'char16_t' AND 'char32_t' as a typdef aliases instead
//// (so they are NOT presented here)
SIGNED_SHORT_INT,
UNSIGNED_SHORT_INT,
SIGNED_INT,
UNSIGNED_INT,
SIGNED_LONG_INT,
UNSIGNED_LONG_INT,
SIGNED_LONG_LONG_INT, // C++11
UNSIGNED_LONG_LONG_INT, // C++11
FLOAT,
DOUBLE,
LONG_DOUBLE,
VOID,
NULLPTR // C++11 std::nullptr_t
};
template <typename T, class TypeTags = ECFundamentalTypeTags>
struct TypeTag {
static const auto TAG = TypeTags::UNIDENTIFIED;
};
template <class TypeTags>
struct TypeTag<bool, TypeTags> {
static const auto TAG = TypeTags::BOOL;
};
template <class TypeTags>
struct TypeTag<signed char, TypeTags> {
static const auto TAG = TypeTags::SIGNED_CHAR;
};
template <class TypeTags>
struct TypeTag<unsigned char, TypeTags> {
static const auto TAG = TypeTags::UNSIGNED_CHAR;
};
template <class TypeTags>
struct TypeTag<wchar_t, TypeTags> {
static const auto TAG = TypeTags::WCHAR;
};
template <class TypeTags>
struct TypeTag<signed short int, TypeTags> {
static const auto TAG = TypeTags::SIGNED_SHORT_INT;
};
template <class TypeTags>
struct TypeTag<unsigned short int, TypeTags> {
static const auto TAG = TypeTags::UNSIGNED_SHORT_INT;
};
template <class TypeTags>
struct TypeTag<signed int, TypeTags> {
static const auto TAG = TypeTags::SIGNED_INT;
};
template <class TypeTags>
struct TypeTag<unsigned int, TypeTags> {
static const auto TAG = TypeTags::UNSIGNED_INT;
};
template <class TypeTags>
struct TypeTag<signed long int, TypeTags> {
static const auto TAG = TypeTags::SIGNED_LONG_INT;
};
template <class TypeTags>
struct TypeTag<unsigned long int, TypeTags> {
static const auto TAG = TypeTags::UNSIGNED_LONG_INT;
};
template <class TypeTags>
struct TypeTag<signed long long int, TypeTags> {
static const auto TAG = TypeTags::SIGNED_LONG_LONG_INT;
};
template <class TypeTags>
struct TypeTag<unsigned long long int, TypeTags> {
static const auto TAG = TypeTags::UNSIGNED_LONG_LONG_INT;
};
template <class TypeTags>
struct TypeTag<float, TypeTags> {
static const auto TAG = TypeTags::FLOAT;
};
template <class TypeTags>
struct TypeTag<double, TypeTags> {
static const auto TAG = TypeTags::DOUBLE;
};
template <class TypeTags>
struct TypeTag<long double, TypeTags> {
static const auto TAG = TypeTags::LONG_DOUBLE;
};
template <class TypeTags>
struct TypeTag<void, TypeTags> {
static const auto TAG = TypeTags::VOID;
};
template <class TypeTags>
struct TypeTag<std::nullptr_t, TypeTags> {
static const auto TAG = TypeTags::NULLPTR;
};
#define TYPE_TAG(Object) TypeTag<decltype(Object)>::TAG
// Size is in bytes
// Fixed width integer types (since C++11): http://e...content-available-to-author-only...e.com/w/cpp/types/integer
// See also: http://w...content-available-to-author-only...4.com/en/t/0012/
template <const size_t Size, const bool Signed>
struct IntegralTypeBySize {
static const auto TAG = ECFundamentalTypeTags::UNIDENTIFIED;
};
template<>
struct IntegralTypeBySize<1U, true> {
typedef int8_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
template<>
struct IntegralTypeBySize<2U, true> {
typedef int16_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
template<>
struct IntegralTypeBySize<4U, true> {
typedef int32_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
template<>
struct IntegralTypeBySize<8U, true> {
typedef int64_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
template<>
struct IntegralTypeBySize<1U, false> {
typedef uint8_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
template<>
struct IntegralTypeBySize<2U, false> {
typedef uint16_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
template<>
struct IntegralTypeBySize<4U, false> {
typedef uint32_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
template<>
struct IntegralTypeBySize<8U, false> {
typedef uint64_t Type;
static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
};
#include <iostream>
template<typename T>
void f(T obj) throw() {
switch(TYPE_TAG(obj)) {
case ECFundamentalTypeTags::SIGNED_INT:
case ECFundamentalTypeTags::UNSIGNED_INT:
std::cout << "int!" << std::endl;
break;
case ECFundamentalTypeTags::SIGNED_LONG_LONG_INT:
case ECFundamentalTypeTags::UNSIGNED_LONG_LONG_INT:
std::cout << "long long int!" << std::endl;
break;
case ECFundamentalTypeTags::FLOAT:
case ECFundamentalTypeTags::DOUBLE:
case ECFundamentalTypeTags::LONG_DOUBLE:
std::cout << "floating point number!" << std::endl;
break;
default:
std::cout << "unknown!" << std::endl;
}
}
#include <cassert>
#include <typeinfo>
int main() {
const BOOL_TYPE(true) btt;
static_assert(btt(), "");
std::cout << btt() << std::endl;
const BOOL_TYPE(false) btf;
static_assert(!btf(), "");
std::cout << btf() << std::endl;
auto v_1_ = false;
static_assert(ECFundamentalTypeTags::BOOL == TYPE_TAG(v_1_), "");
auto v_2_ = 0;
static_assert(ECFundamentalTypeTags::SIGNED_INT == TYPE_TAG(v_2_), "");
auto v_3_ = 0L;
static_assert(ECFundamentalTypeTags::SIGNED_LONG_INT == TYPE_TAG(v_3_), "");
auto v_4_ = 0ULL;
static_assert(ECFundamentalTypeTags::UNSIGNED_LONG_LONG_INT == TYPE_TAG(v_4_), "");
f(1), f(1ULL), f(1.0), f(1.0L);
IntegralTypeBySize<sizeof(char), true>::Type t1_ = 0;
static_assert(sizeof(t1_) == sizeof(char), "");
static_assert(std::is_integral<decltype(t1_)>::value && std::is_signed<decltype(t1_)>::value, "");
IntegralTypeBySize<sizeof(int), true>::Type t2_ = 0;
static_assert(sizeof(t2_) == sizeof(int), "");
static_assert(std::is_integral<decltype(t2_)>::value && std::is_signed<decltype(t2_)>::value, "");
IntegralTypeBySize<sizeof(long long int), true>::Type t4_ = 0;
static_assert(sizeof(t4_) == sizeof(long long int), "");
static_assert(std::is_integral<decltype(t4_)>::value && std::is_signed<decltype(t4_)>::value, "");
const IntegralTypeBySize<8U, false>::Type array[32U] = {0};
std::cout << "\ni've got a " << sizeof(array) / sizeof(*array) << " length array of "
<< typeid(*array).name() << "s here!\n";
return 0;
}