以下代码尝试(不使用c ++ 11)创建特征以识别类型是否可以STL方式迭代:
#include <iostream>
#include <vector>
template<typename C>
struct IsIterable
{
typedef char true_type;
typedef long false_type;
template<class T> static true_type is_beg_iterable(
typename T::const_iterator = C().begin());
template<class T> static false_type is_beg_iterable(...);
enum { value = sizeof(is_beg_iterable<C>()) == sizeof(true_type) };
};
int main() {
std::cout << IsIterable<std::vector<int>>::value << std::endl;
}
还有is_end_iterable
方法,为简洁起见,此处省略
代码 fails与gcc 4.9.2 *(以及旧版本)并在VS2012中成功并成功。我的断言是,可变参数版本总是在重载决策中排在最后(因此不应该有歧义),所以谁在这里?
是否存在跨平台解决方案/替代方案?
我现在看到VS的新版本也拒绝了代码,因此最后一个问题变得更加重要
答案 0 :(得分:3)
只有当函数的实际参数与省略号转换更好匹配时才有效。请记住,没有参数的默认值参数不参与重载决策。
解决方案是添加另一个参数并传递一个参数:
template<class T> static true_type is_beg_iterable(int, // <- for disambiguation
typename T::const_iterator = C().begin());
template<class T> static false_type is_beg_iterable(...);
enum { value = sizeof(is_beg_iterable<C>(0)) == sizeof(true_type) };
// ^
答案 1 :(得分:2)
答案 2 :(得分:1)
以下作品(至少使用gcc 4.9.2):
template<typename C>
struct IsIterable
{
typedef char true_type;
typedef long false_type;
template<class T> static true_type is_beg_iterable(int,
typename T::const_iterator = C().begin());
template<class T> static false_type is_beg_iterable(...);
enum { value = sizeof(is_beg_iterable<C>(0)) == sizeof(true_type) };
};