今天,我试图对某个类是否具有嵌套类型reverse_iterator
执行类型切换。我在这些论坛上发现了一些有效的解决方案,其中包括以下内容:
template<typename T>
struct is_reverse_iterable
{
using yes = uint8_t;
using no = uint16_t;
template<typename U>
static yes& test(typename U::reverse_iterator*);
template<typename>
static no& test(...);
static constexpr bool value = sizeof(test<T>(0)) == sizeof(yes);
};
如果我只是从main检查条件,这个类工作得很好,但是,我也写了一个小函数,这会导致一些问题。
template<typename T>
void foo(T&& iter)
{
std::cout << typeid(T).name() << std::endl;
std::cout << is_reverse_iterable<T>::value << std::endl;
}
这是导致我出现问题的主要原因:
int main()
{
using namespace std;
vector<int> v;
cout << typeid(decltype(v)).name() << endl;
cout << is_reverse_iterable<decltype(v)>::value << endl;
foo(v);
return 0;
}
由于std::vector<int>
包含嵌套类型名称reverse_iterator
,人们会认为 - 或者至少,我认为 - is_reverse_iterable<vector<int>>::value
无论我放在哪里都会返回true。但事实并非如此。以下是主要结果:
St6vectorIiSaIiEE
1
St6vectorIiSaIiEE
0
从main调用时,结构is_reverse_iterable
在reverse_iterator
中识别出名称vector<int>
,但在从foo
调用时却没有这样做。实际上,我不知道为什么,我希望有人请向我解释问题是什么:)
P.S。 :我使用MinGW g ++ 4.7.1编译,使用选项-std = c ++ 11。
答案 0 :(得分:1)
问题在于,当您致电foo(v)
时,会推断出T
类型为std::vector<int>&
(左值 - 参考),因此{{ 1}}将无法编译。您可以自己轻松检查:
typename T::reverse_iterator
收率:
template<typename T>
void foo(T&& iter)
{
std::cout << typeid(T).name() << std::endl;
std::cout << is_reverse_iterable<T>::value << std::endl;
typename T::reverse_iterator t; // <-- add this line to see what's wrong
}
解决方案很简单:在启动SFINAE之前删除引用,例如
3.cpp: In instantiation of ‘void foo(T&&) [with T = std::vector<int>&]’:
3.cpp:40:10: required from here
3.cpp:27:34: error: ‘std::vector<int>&’ is not a class, struct, or union type