Reputation: 201
I am writing a generic branch and bound algorithm using templates, in C++17.
The code compiles (and runs) fine when I supply the default template argument 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);
// ...
}
However, g++ (7.3.0) complains that it cannot deduce the template parameter RealFun2 if I do not give the default:
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);
I do not understand the circumstances under which supplying a default should be necessary or not.
Upvotes: 0
Views: 75
Reputation: 55395
So, on to the first part of the error message
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>)’
The part unresolved overloaded function type> marks the parameter where you pass lower_bound
. It means that there are more functions with that name and the compiler can't decide which one you mean.
There are std::lower_bound
functions in <algorithm>
header, which means you've got using namespace std;
somewhere.
It should now be obvious why it works when there's default for the last template parameter - the compiler doesn't have to guess the type.
Upvotes: 2
Reputation: 201
The problem turns out to be the name of the function, in the function definition float lower_bound(Repr)
. Unfortunately, lower_bound
clashes with a function from the Standard Library in <algorithm>
. Without the template default, the compiler had not enough information to distinguish between the user-provided function and the standard library one.
Upvotes: 1