determine whether wchar_t is a built-in type or alias

Viewed 259

Yes, wchar_t is supposed to be a built-in type in C++; unfortunately, that's not the case with some (very) old compilers.

Is there a (compiler-specific, e.g., GCC/g++) way to determine whether wchar_t is a built-in type (keyword) or a typedef? The reason is to determine whether f(wchar_t) can be an overload; if wchar_t is a typedef, it will (very likely) be the same as f(uint16_t) or f(uint32_t).

Microsoft Visual C++ has _NATIVE_WCHAR_T_DEFINED so I can write:

#include <stdint.h>

#if defined(_MSC_VER)
   #define MY_PROJECT_wchar_t_is_built_in_ (_NATIVE_WCHAR_T_DEFINED == 1)
#else
   #define MY_PROJECT_wchar_t_is_built_in_ 1
#endif

void f(uint16_t ch_utf16) { /* UTF-16 processing */ }
void f(uint32_t ch_utf32) { /* UTF-32 processing */ }

#if MY_PROJECT_wchar_t_is_built_in_
   #include <type_traits>
   void f(whcar_t ch_)
   {
      using wchar_t_type = std::conditional<sizeof(wchar_t) == sizeof(uint32_t), uint32_t, uint16_t>::type;
      #ifdef _WIN32
      static_assert(sizeof(wchar_t_type) == sizeof(uint16_t), "wchar_t should be 16-bits on Windows.");
      #endif
      const auto ch = reinterpret_cast<wchar_t_type>(ch_);
      f(ch);
   }
#endif

Extensive TMP probably won't work (e.g., std::enable_if) ... as it's an old compiler causing the problem in the first place!

1 Answers

Ayxan Haqverdili's suggestion in comment of using a template with sizeof() solves my problem. (It also illustrates why sufficient context regarding "why?" is necessary.)

My code is now:

void f_(uint16_t ch_utf16) { /* UTF-16 processing */ }
void f_(uint32_t ch_utf32) { /* UTF-32 processing */ }

template<typename T>
void f(T ch_)
{
    static_assert(sizeof(T) == sizeof(wchar_t), "T should be wchar_t");

    if (sizeof(T) == sizeof(uint16_t))
    {
        const auto ch = reinterpret_cast<uint16_t>(ch_);
        f_(ch);
    }
    else if (sizeof(T) == sizeof(uint32_t))
    {
        const auto ch = reinterpret_cast<uint32_t>(ch_);
        f_(ch);
    }
    else
    {
        throw ...;
    }
}
Related