如何仅允许具有特定value_type的迭代器传入类构造函数?
如何在迭代器构造函数中编译期检查value_type匹配?
我想编写一个以一对迭代器作为构造函数参数的类,希望在编译时触发错误——当这些迭代器的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 << "constr..."; } };
其实你用typeid的方式并不推荐,因为typeid本质是运行时的类型查询操作,虽然这里靠数组大小为负会触发编译错误,但这属于“hack”手法,不仅不是标准的编译期检查方式,而且报错信息会非常晦涩,不利于排查问题。
正确的做法是用C++11及以后标准提供的static_assert,这是专门用来做编译期断言的工具,能给你清晰的错误提示。
修改后的代码:
#include <vector> #include <type_traits> // 必须包含这个头文件来使用std::is_same #include <iostream> struct foo { std::vector<double> data; template <typename IT> foo(IT begin, IT end){ // C++11及以后兼容的写法 static_assert( std::is_same<typename IT::value_type, double>::value, "错误:迭代器的value_type必须是double!" ); // 如果你的项目支持C++17,可以用更简洁的is_same_v // static_assert( // std::is_same_v<typename IT::value_type, double>, // "错误:迭代器的value_type必须是double!" // ); data.assign(begin, end); // 顺便把迭代器范围的数据存入成员 std::cout << "constr..."; } };
更通用的写法(支持原生指针):
如果你的迭代器可能是原生指针(比如double*),用std::iterator_traits来获取value_type会更通用,它能同时处理容器迭代器和原生指针:
static_assert( std::is_same_v<typename std::iterator_traits<IT>::value_type, double>, "错误:迭代器的value_type必须是double!" );
这样当你传入std::vector<int>::iterator这类不匹配的迭代器时,编译器会直接弹出你定义的错误提示,清晰明了,而且是标准的编译期检查,兼容性拉满。
内容的提问来源于stack exchange,提问作者463035818_is_not_an_ai
相关产品推荐
相关产品推荐

