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!
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 ...;
}
}