Skip to content

Instantly share code, notes, and snippets.

@robin92
Last active January 19, 2017 08:46
Show Gist options
  • Save robin92/9dab677151df04c62e41a8c987491047 to your computer and use it in GitHub Desktop.
Save robin92/9dab677151df04c62e41a8c987491047 to your computer and use it in GitHub Desktop.
cpp metaprogramming, is_container (sfinae for templates)
// 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