如何用enable_if根据迭代器指向类型启用C++模板函数?
解决C++17中迭代器类型的SFINAE适配问题
你原有的函数通过static_assert在函数内部校验迭代器指向元素的大小,但希望把错误提前到调用阶段,同时移除static_assert。你尝试的enable_if写法有误,导致无论迭代器类型如何都无法匹配函数。
原函数代码
template<typename input_iterator> std::string doit(input_iterator beg, input_iterator end) { static_assert(sizeof(*beg) == 1, "Size one only, please"); return do_something(beg, end); }
错误尝试的问题
你的enable_if写法缺少必要的类型声明和默认值,编译器无法识别合法的模板参数,导致所有调用都找不到匹配的函数:
// 错误写法:缺少::type和默认值 template<typename input_iterator, std::enable_if<sizeof(std::iterator_traits<input_iterator>::value_type) == 1>> std::string doit(input_iterator beg, input_iterator end) { return do_something(beg, end); }
两种C++17兼容的正确写法
写法1:将enable_if作为模板参数的默认类型
#include <iterator> // 必须包含此头文件以使用iterator_traits template<typename input_iterator, typename = std::enable_if_t<sizeof(std::iterator_traits<input_iterator>::value_type) == 1>> std::string doit(input_iterator beg, input_iterator end) { return do_something(beg, end); }
这里使用std::enable_if_t(C++14引入,等价于typename std::enable_if<...>::type),并给匿名模板参数设置默认值。当迭代器指向元素大小为1时,模板正常实例化;否则SFINAE机制会排除该模板,调用处直接报无匹配函数的错误。
写法2:将enable_if嵌入返回值类型
#include <iterator> template<typename input_iterator> std::enable_if_t<sizeof(std::iterator_traits<input_iterator>::value_type) == 1, std::string> doit(input_iterator beg, input_iterator end) { return do_something(beg, end); }
这种写法通过返回值类型的SFINAE过滤不满足条件的模板实例,效果和写法1一致,错误会在调用阶段抛出。
注意事项
- 必须包含
<iterator>头文件,因为std::iterator_traits定义在此处,否则会出现编译错误。 - 两种写法都能在C++17中正常编译,且错误提示会出现在函数调用的位置,而非函数内部。
内容的提问来源于stack exchange,提问作者jkb
相关产品推荐
相关产品推荐

