为什么模板扣除需要默认模板

Why can a default template be necessary for template deduction?

本文关键字:默认 为什么      更新时间:2023-10-16

我在 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> 年标准库中的功能发生冲突。如果没有模板默认值,编译器没有足够的信息来区分用户提供的函数和标准库函数。

相关文章: