【发布时间】:2018-03-19 08:42:54
【问题描述】:
我想编写一个将一对迭代器作为构造函数参数的类,但是当这些迭代器的value_type 与预期类型不匹配时,我不知道如何在编译时引发错误。这是我尝试使用typeid:
#include <vector>
struct foo {
std::vector<double> data;
template <typename IT>
foo(IT begin, IT end){
typedef int static_assert_valuetype_is_double[
typeid(typename IT::value_type) == typeid(double) ? 1 : -1
];
std::cout << "constructor called \n";
data = std::vector<double>(begin,end);
}
};
int main()
{
std::vector<double> x(5);
foo f(x.begin(),x.end()); // double: ok
std::vector<int> y(10);
foo g(y.begin(),y.end()); // int: should not compile
}
请注意,在这种情况下,int 到 double 可以,但这只是一个示例,在实际代码中,类型必须完全匹配。令我惊讶的是,在这两种情况下,构造函数都没有错误(只有关于未使用的 typedef 的警告)。当 typedef 在方法中声明时,-1 大小的数组静态断言技巧是否不起作用? IT::value_type 是错误类型时如何产生错误?
PS:如果有一个简单的 C++98 解决方案会很好,但如果太复杂,我也可以接受 C++11 解决方案。
【问题讨论】:
-
double*是一个有效的迭代器,其值类型显然是double,但double*没有嵌套的double*::value_type。我想你需要typeid(*begin) -
@MSalters 抱歉,如果我的问题不清楚。我主要关心标准容器及其迭代器。如果一个解决方案排除了一些奇异的迭代器,那不是问题
-
嗯,指针并不陌生,它们是数组的自然迭代器。见
std::begin(MyArray) -
这并没有解决问题,但构造函数应该使用初始化列表,而不是为构造函数主体中的(默认构造的)向量分配新值。所以:
foo(IT begin, IT end) : data(begin, end) { /* static assert goes here */ }。一般来说,除非有充分的理由延迟设置正确的值,否则对所有成员使用初始化列表。 -
@PeterBecker 我通常总是这样做,不知道为什么我没有在这里这样做。实际上,如果构造函数的主体与
{}不同,我会感到紧张
标签: c++ iterator typechecking c++98 static-assert