为什么模板扣除需要默认模板
Why can a default template be necessary for template deduction?
我在 C++17 中使用模板编写一个通用分支和绑定算法。
当我提供默认模板参数 RealFun2 = RealFun1 时,代码编译(并运行)良好:
template <typename Repr, typename SplFun, typename Predicate,
typename RealFun1, typename RealFun2=RealFun1>
optional<Repr> branch_and_bound(Repr r0, SplFun split, Predicate goal,
RealFun1 F, RealFun2 lower_bound) {
optional<Repr> BEST;
float F_BEST = INFINITY;
stack<Repr> ACTIVE; ACTIVE.push(r0);
while(!ACTIVE.empty()) {
Repr r = ACTIVE.top(); ACTIVE.pop();
if(goal(r)) {
if(F(r) < F_BEST) {
BEST = r;
F_BEST = F(r);
}
}
else
for(Repr q: split(r))
if(lower_bound(q) < F_BEST)
ACTIVE.push(q);
}
return BEST;
}
struct knapsack { /* ... */ };
using Repr = pair<knapsack, vector<int>>;
bool goal(Repr r) { /* ... */ }
float F(Repr r) { /* ... */ }
vector<Repr> split(Repr r) { /* ... */ }
float lower_bound(Repr r) { /* ... */ }
int main() {
// ...
knapsack K(N, cap, weight, value);
Repr r0(K, vector<int>(N, 0));
optional<Repr> BEST = branch_and_bound(r0, split, goal, F, lower_bound);
// ...
}
但是,g++ (7.3.0) 抱怨如果我不给出默认值,它就无法推断出模板参数 RealFun2
:template <typename Repr, typename SplFun, typename Predicate,
typename RealFun1, typename RealFun2>
// rest of code is the same
KNAPBB.cpp:105:72: error: no matching function for call to ‘branch_and_bound(Repr&, std::vector<std::pair<knapsack, std::vector<int> > > (&)(Repr), bool (&)(Repr), float (&)(Repr), <unresolved overloaded function type>)’
optional<Repr> BEST = branch_and_bound(r0, split, goal, F, lower_bound);
BRABOUND.cpp:11:16: note: template argument deduction/substitution failed:
KNAPBB.cpp:105:72: note: couldn't deduce template parameter ‘RealFun2’
optional<Repr> BEST = branch_and_bound(r0, split, goal, F, lower_bound);
我不明白在什么情况下有必要提供违约。
因此,转到错误消息的第一部分
no matching function for call to ‘branch_and_bound(Repr&,
std::vector<std::pair<knapsack, std::vector<int> > > (&)(Repr), bool(&)(Repr), float (&)(Repr), <unresolved overloaded function type>)’
部件未解析重载函数类型>标记传递lower_bound
的参数。这意味着有更多具有该名称的函数,编译器无法确定您指的是哪一个。
<algorithm>
标题中有std::lower_bound
函数,这意味着您在某处using namespace std;
。
现在应该很清楚为什么当最后一个模板参数有默认值时它有效 - 编译器不必猜测类型。
问题原来是函数的名称,在函数定义float lower_bound(Repr)
中。不幸的是,lower_bound
与 <algorithm>
年标准库中的功能发生冲突。如果没有模板默认值,编译器没有足够的信息来区分用户提供的函数和标准库函数。
相关文章:
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 当给定默认值时,为什么此模板参数推导失败
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- 为什么默认复制函数在按值发送参数时不调用?
- 为什么我的开关/机箱在使用枚举时默认?
- 为什么即使我调用参数化构造函数也会调用默认构造函数?
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 为什么C++构造函数在继承中需要默认参数?
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- 为什么为派生类定义复制构造函数需要定义基类的默认构造函数?
- 为什么指针对象没有调用默认构造函数
- 为什么对象默认初始化,但基元不在C++?
- 为什么不接受具有默认分配参数的函数作为 0-arg 生成器?
- 为什么在使用指针时不采用类成员的默认值,而不是直接实例化对象时?
- 为什么使用默认构造函数"{}"而不是"= default"存在性能变化?
- 为什么 std::move 不将默认移动构造函数中的源变量更改为默认值?
- 为什么"/usr/include"不在 GCC 默认搜索路径中
- 为什么我的对象声明不调用默认构造函数?