为什么模板推导需要默认模板?

时间:2019-01-17 11:17:11

标签: c++ templates

我正在C ++ 17中使用模板编写通用的branch and bound算法。

当我提供默认模板参数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);

我不了解在什么情况下是否需要提供默认值。

2 个答案:

答案 0 :(得分:2)

因此,在错误消息的第一部分

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;

现在很明显,当最后一个模板参数为默认值时,为什么它可以工作-编译器不必猜测类型。

答案 1 :(得分:1)

问题原来是函数定义x0中的函数名称。不幸的是,float lower_bound(Repr)lower_bound中标准库中的函数冲突。没有模板默认值,编译器将没有足够的信息来区分用户提供的功能和标准库。