所以,这就是我调试这些东西的方法。
首先,注释掉否定的选择,这样你就会得到一个错误,而不仅仅是一个不匹配。接下来,尝试使用其中一项不起作用的项来实例化您要放入函数的类型。
在这一步,我能够实例化您的 sfinae 对象,但它仍然无法正常工作。“这让我知道这是一个 VS 错误,所以问题是如何修复它。” -- OBS
当你按照你的方式完成时,VS 似乎在使用 SFINAE 时遇到了麻烦。当然可以! 包裹 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'
这让我知道VS(任何编译器)能够分辨出我想要哪个 end()&U::end
是不够的。 一个 static_cast 修复了:
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++ 应该失败了。