Итак, вот как я отлаживаю эти вещи.
Сначала закомментируйте отрицательную альтернативу, чтобы вы получили ошибку, а не просто несоответствие.
Затем попробуйте создать экземпляр типа, который вы вводите в функцию, с одним из элементов, которые не работают.
На этом этапе я смог создать экземпляр вашего объекта sfinae, но он все еще не работал. «Это дает мне понять, что это ошибка VS, поэтому вопрос в том, как ее исправить». - OBS
Кажется, у VS проблемы с SFINA, когда все сделано так, как ты. Конечно, это так! Это работает лучше, когда вы заверните свой объект sfinae. Я сделал это так:
template <typename U, typename it_t = typename U::const_iterator >
struct sfinae
{
// typedef typename U::const_iterator it_t; - fails to compile with non-cont types. Not sfinae
template < typename U, typename IT, IT (U::*)() const, IT (U::*)() const >
struct type_ {};
typedef type_<U,it_t,&U::begin,&U::end> type;
};
Все еще не работал, но по крайней мере я получил полезное сообщение об ошибке:
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'std::_Tree_const_iterator<_Mytree> (__thiscall std::set<_Kty>::* )(void) const'
Это позволяет мне знать, что &U::end
недостаточно для того, чтобы VS ( ANY компилятор) мог определить, какой конец () мне нужен. Статический_каст исправляет это :
typedef type_<U,it_t,static_cast<it_t (U::*)() const>(&U::begin),static_cast<it_t (U::*)() const>(&U::end)> type;
Соберите все вместе и запустите на нем свою тестовую программу ... успех с VS2010. Вы можете обнаружить, что static_cast - это действительно все, что вам нужно, но я оставил это вам, чтобы узнать.
Полагаю, реальный вопрос сейчас в том, какой компилятор прав? Моя ставка на тот, который был последовательным: g ++. Укажите на мудрого: НИКОГДА предположите, что я тогда сделал.
Редактировать: Боже ... Вы ошибаетесь!
Исправленная версия:
template <typename T>
struct is_container
{
template <typename U, typename it_t = typename U::const_iterator >
struct sfinae
{
//typedef typename U::const_iterator it_t;
template < typename U, typename IT, IT (U::*)() const, IT (U::*)() const >
struct type_ {};
typedef type_<U,it_t,static_cast<it_t (U::*)() const>(&U::begin),static_cast<it_t (U::*)() const>(&U::end)> type;
};
template <typename U> static char test(typename sfinae<U>::type*);
template <typename U> static long test(...);
enum { value = (1 == sizeof test<T>(0)) };
};
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>
int main()
{
std::cout << is_container<std::vector<std::string> >::value << ' ';
std::cout << is_container<std::list<std::string> >::value << ' ';
std::cout << is_container<std::set<std::string> >::value << ' ';
std::cout << is_container<std::map<std::string, std::string> >::value << ' ';
std::cout << is_container<bool>::value << '\n';
}
-
Отладка выше разумна, но предположение о компиляторе было ошибочным. G ++ должен был потерпеть неудачу по причине, которую я подчеркнул выше.