Así que, aquí es cómo voy a depurar estas cosas.
Primero, comente la alternativa negativa para que obtenga un error en lugar de una discrepancia. A continuación, intente crear una instancia del tipo que está poniendo en la función con uno de los elementos que no funcionan.
En este paso, pude crear una instancia de su objeto sfinae pero todavía no funcionaba. Esto me permite saber que ES un error de VS, por lo que la pregunta es cómo solucionarlo.
VS parece tener problemas con SFINAE cuando está hecho como está. Funciona mejor cuando envuelve su objeto sfinae. Lo hice así:
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;
};
Aún no estaba funcionando, pero al menos tengo un mensaje de error útil:
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'std::_Tree_const_iterator<_Mytree> (__thiscall std::set<_Kty>::*)(void) const'
Esto me deja saber que &U::end
no es suficiente para VS a ser capaz de decir qué final() quiero. Un static_cast fija que:
typedef type_<U,it_t,static_cast<it_t (U::*)() const>(&U::begin),static_cast<it_t (U::*)() const>(&U::end)> type;
poner todo de nuevo juntos y ejecutar su programa de pruebas en él ... éxito con VS2010. Es posible que encuentre que static_cast es en realidad todo lo que necesita, pero se lo dejé saber.
Supongo que la verdadera pregunta ahora es, ¿qué compilador tiene razón? Mi apuesta es la que fue consistente: g ++.
Editar: Jeesh ...
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';
}
Funcionó para mí en MinGW g ++ 4.4.0 (obtuvo '1 1 1 1'). Desafortunadamente no tengo idea de por qué falla en VS2008, aunque el código parece correcto. –
Lo mismo en VS2010 '1 1 0 0'. Tenía la corazonada de que podría estar depurando STL, así que probé '/ DDEBUG' y'/DNDEBUG' pero no hizo ninguna diferencia. – Rup
Puede echar un vistazo a la instalación ['HAS_XXX'] (http://live.boost.org/doc/libs/1_34_0/boost/mpl/has_xxx.hpp) proporcionada por Boost.MPL para ver cómo funcionan. capacidades SFINAE limitadas de ciertos compiladores. –