为什么重载分辨率不选择第一个函数?
Why doesn't overload resolution pick the first function?
在下面的程序中,两个函数调用都打印"非积分重载",即使我有一个enable_if
语句将函数限制为仅整型容器类型。为什么?
#include <iostream>
#include <vector>
#include <type_traits>
template<bool B, typename V = void>
using enable_if = typename std::enable_if<B, V>::type;
template<typename ForwardIt>
auto f(ForwardIt first, ForwardIt)
-> enable_if<std::is_integral<decltype(*first)>{}>
{
std::cout << "Integral container type" << std::endl;
}
template<typename ForwardIt>
void f(ForwardIt, ForwardIt)
{
std::cout << "Non-integral container type" << std::endl;
}
int main()
{
struct X { };
std::vector<int> iv;
std::vector<X> xv;
f(iv.begin(), iv.end()); // "Non-integral container type"
f(xv.begin(), xv.end()); // "Non-integral container type"
}
我什至尝试在第二次重载上使用enable_if<!std::is_integral<...>>
但无济于事。
另一个答案已经解释了这个问题,但我认为有更好的解决方案。
如果要提取迭代器类型指向的类型,则应使用iterator_traits
。在代码中,将第一个重载更改为:
template<typename ForwardIt>
auto f(ForwardIt first, ForwardIt)
-> enable_if<std::is_integral<typename std::iterator_traits<ForwardIt>::value_type>{}>
{
std::cout << "Integral container type" << std::endl;
}
并在第二个上使用相同的附加!
。这更具描述性,因为代码非常清楚它的作用。
现场示例
对于迭代器类型 foo
,decltype(*foo)
将是foo::value_type&
。引用类型绝对不是整数的。在评估具有std::is_integral
特征的类型之前,您需要删除引用(可能还有 cv 限定,IIRC),这很容易通过std::decay
转换类型特征完成:
template<bool B, typename V = void>
using enable_if = typename std::enable_if<B, V>::type;
template<typename T>
using decay = typename std::decay<T>::type;
template<typename ForwardIt>
auto f(ForwardIt first, ForwardIt)
-> enable_if<std::is_integral<decay<decltype(*first)>>{}>
{
std::cout << "Integral container type" << std::endl;
}
这将导致与您的其他重载不明确,因为两者现在将匹配。您需要按照 OP 中的建议约束第二个重载。
相关文章:
- "main"函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)
- 使第二个类的构造函数成为第一个类中的友元函数
- 静态堆栈函数不会 1) 输入第一个元素 2)添加新元素时识别旧元素
- 候选构造函数(隐式复制构造函数)不可行:第一个参数需要 l 值
- 在类的第一个/最后一个实例存在之前/之后调用一对函数.有没有更好的方法?
- 函数返回两个字符串的第一个常用字符
- 为什么 std::error_code 构造函数的第一个参数固定为 int
- 对c++中的输入使用getline函数时忽略第一个字符
- 我必须更改我的数字最后一个数字和第一个数字,但不要使用仅带有整数或循环的函数.例如从 12345 到 52341
- 如何通过 std::apply 调用具有定义的第一个参数的可变参数模板函数?
- 尝试将参数包的第一个元素作为函数调用,并将包的其余部分作为参数传递给它
- 如果 x,递归不起作用,我的函数只能删除第一个元素
- 初始化类构造函数初始化列表中的对象数组的第一个条目
- 如何显示我在第一个函数中已经创建的文件的内容
- 在函数中删除第一个元素后,如何更新链接列表的phead
- 为什么我的程序跳过第一个函数?(初学者C++)
- 第一个函数中的无限循环不知道如何解决
- 为什么重载分辨率不选择第一个函数?
- 为什么第一个函数调用绑定到第一个函数
- 调用第三个函数后如何返回第一个函数