Last active
December 31, 2016 09:59
-
-
Save polyvertex/29d0e7952b5bb1e33d7cf4a6592ec332 to your computer and use it in GitHub Desktop.
Deduce the char type of virtually any literal or container (C++11)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// char_type_of: deduce the char type of virtually any literal or | |
// container (C++11 SFINAE at its finest) | |
// Original author: Jean-Charles Lefebvre <[email protected]> | |
// 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