#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <list>
#include <queue>
#include <deque>
#include <tuple>
template < template <typename...> class U, typename T >
struct is_template_instance_of : std::false_type {
};
template < template <typename...> class U, typename... args >
struct is_template_instance_of< U, U<args...> > : std::true_type {
};
template <typename T>
struct is_stdstring : is_template_instance_of < std::basic_string, T > {
};
template <class T>
struct is_tuple : is_template_instance_of <std::tuple, T> {
};
template <class T>
struct is_sequential_container : std::integral_constant<bool, is_template_instance_of<std::list, T>::value ||
is_template_instance_of<std::queue, T>::value ||
is_template_instance_of<std::deque, T>::value ||
is_template_instance_of<std::vector, T>::value> {
// static_assert(std::is_same<std::list<int>, T>::value == 1, "std::list<int>");
};
template <class T>
struct is_associated_container : std::integral_constant<bool, is_template_instance_of<std::map, T>::value ||
is_template_instance_of<std::unordered_map, T>::value > {
};
class Test {
};
int main() {
std::string str = "ABC";
std::cout << is_stdstring<std::string>::value << std::endl;
std::cout << is_stdstring<char *>::value << std::endl;
std::cout << is_sequential_container<std::list<int>>::value << std::endl;
std::cout << is_sequential_container<Test>::value << std::endl;
std::cout << is_associated_container<std::map<int, int>>::value << std::endl;
return 0;
}