Last active
January 19, 2017 08:46
-
-
Save robin92/9dab677151df04c62e41a8c987491047 to your computer and use it in GitHub Desktop.
cpp metaprogramming, is_container (sfinae for templates)
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
// taken from http://stackoverflow.com/a/31207079 | |
// assuming that only containers have value_type | |
#include <cassert> | |
#include <vector> | |
namespace detail { | |
// the whole point of this structure is to get template-based sfinae working | |
template <class... _> struct resolved {}; | |
} // namespace detail | |
// template partial specialization mechanism is necessary hence 2nd arg | |
template <class T, class _ = void> | |
struct is_container : public std::false_type {}; | |
// partial template specialization | |
// at first sight std::conditional would always result in 3rd argument (void) but | |
// it needs to deduce types first which may fail on 2nd argument; thanks to | |
// sfinae such an failure is not an error and the compiler tries another struct | |
template <class T> | |
struct is_container<T, std::conditional_t< | |
false, | |
detail::resolved<typename T::value_type>, | |
void | |
>> : public std::true_type {}; | |
template <class T> constexpr bool is_container_v = is_container<T>::value; | |
struct Foo {}; | |
struct Bar { using value_type = void; }; | |
int main(int, char**) { | |
assert(!is_container_v<Foo>); | |
assert(is_container_v<Bar>); | |
assert(is_container_v<std::vector<int>>); | |
assert(!is_container_v<int>); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment