65,210
社区成员
发帖
与我相关
我的任务
分享#include <iostream>
#include <iterator>
#include <string>
template<typename T>
struct has_const_iterator {
template<typename C> static char test(const typename C::const_iterator*);
template<typename C> static long test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(char);
typedef T type;
};
template <typename T>
struct has_begin_end {
struct Dummy { typedef void const_iterator; };
typedef typename std::conditional<has_const_iterator<T>::value, T, Dummy>::type TCompatible;
typedef typename TCompatible::const_iterator TIter;
struct Fallback { TIter begin() const; TIter end() const; };
struct Derived : public TCompatible, public Fallback { };
template<typename C, C> struct TWapper;
template<typename C> static char b(TWapper<TIter (Fallback::*)() const, &C::begin>*);
template<typename C> static long b(...);
template<typename C> static char e(TWapper<TIter (Fallback::*)() const, &C::end>*);
template<typename C> static long e(...);
static bool const beg_value = sizeof(b<Derived>(0)) == sizeof(long);
static bool const end_value = sizeof(e<Derived>(0)) == sizeof(long);
};
template<typename T>
struct is_container {
static const bool value = has_const_iterator<T>::value &&
// !std::is_same<char, typename T::const_iterator::value_type>::value &&
has_begin_end<T>::beg_value && has_begin_end<T>::end_value;
};
int main(int argc, char* argv[]) {
std::cout << std::boolalpha << is_container<std::string>::value << std::endl;
}
struct test_t { };
int main ()
{
std::cout << std::boolalpha << is_container<test_t>::value << std::endl;
}
因为 test_t::const_iterator 不存在,所以 std::is_same 的第二个模板参数会出问题,导致编译错误。这种情况使用 traits 就行了,比如:
template <typename T, bool = has_const_iterator<T>::value>
struct value_type_traits
{
using value_type = void; // dummy type when T has no const_iterator
};
template <typename T>
struct value_type_traits<T,true>
{
using value_type = typename T::const_iterator::value_type;
};
template<typename T>
struct is_container {
static const bool value = has_const_iterator<T>::value &&
!std::is_same<char, typename value_type_traits<T>::value_type>::value &&
has_begin_end<T>::beg_value && has_begin_end<T>::end_value;
};
struct test_t { };
int main ()
{
std::cout << std::boolalpha << is_container<std::string>::value << std::endl;
std::cout << std::boolalpha << is_container<std::vector<int>>::value << std::endl;
std::cout << std::boolalpha << is_container<std::list<float>>::value << std::endl;
std::cout << std::boolalpha << is_container<std::set<size_t>>::value << std::endl;
std::cout << std::boolalpha << is_container<test_t>::value << std::endl;
}