Skip to content

Instantly share code, notes, and snippets.

@polyvertex
Last active December 31, 2016 09:59
Show Gist options
  • Save polyvertex/29d0e7952b5bb1e33d7cf4a6592ec332 to your computer and use it in GitHub Desktop.
Save polyvertex/29d0e7952b5bb1e33d7cf4a6592ec332 to your computer and use it in GitHub Desktop.
Deduce the char type of virtually any literal or container (C++11)
// char_type_of: deduce the char type of virtually any literal or
// container (C++11 SFINAE at its finest)
// Original author: Jean-Charles Lefebvre <polyvertex@gmail.com>
// util: an almighty version of std::decay<>, with super powers
template <typename T>
struct super_decay
{
typedef
typename std::remove_cv<
typename std::remove_pointer<
typename std::remove_reference<
typename std::remove_extent<
typename std::decay<T>::type>::type>::type>::type>::type type;
};
// util: a shortcut to super_decay<T>::type
template <typename T>
using super_decay_t = typename super_decay<T>::type;
// implementation details of char_type_of
namespace detail
{
template <typename T>
struct char_type_spec { };
template <> struct char_type_spec<char> { typedef char type; };
template <> struct char_type_spec<wchar_t> { typedef wchar_t type; };
template <> struct char_type_spec<char16_t> { typedef char16_t type; };
template <> struct char_type_spec<char32_t> { typedef char32_t type; };
// This specialization should work for "any" container type that exposes the
// value_type type (typically std::basic_string, std::vector, ...)
template <template<typename...> typename Container, typename... Args>
struct char_type_spec<typename Container<Args...>>
{
typedef typename Container<Args...>::value_type contvt_;
// * std::is_integral helps to ensure we're not going to recurse
// * Re-using char_type_spec<> allows to ensure Container::value_type
// type is supported
typedef std::enable_if_t<
std::is_integral<contvt_>::value,
typename char_type_spec<contvt_>::type> type;
};
}
// Deduce the type of char from the given type T.
// If no char_type_spec<> has been specialized for the specified type,
// msvc will spit error C2039 ('type': is not a member of...)
template <typename T>
struct char_type_of
{
typedef
typename detail::char_type_spec<typename super_decay_t<T>>::type type;
};
// A shortcut to char_type_of<T>::type
template <typename T>
using char_type_of_t = typename char_type_of<T>::type;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment