ksh*_*noy 7 c++ templates template-argument-deduction
我正在尝试使用可选参数创建模板化函数,但我无法理解编译失败的原因.这是我的测试(人为)代码:
#include <iostream>
#include <vector>
template <class UnaryPredicate>
int GetCountIf(std::vector<int> v, UnaryPredicate pred = [](auto) { return true; }) {
int count=0;
for (auto i: v) {
if (pred(i)) {
count++;
}
}
return count;
}
int main() {
auto v = std::vector<int>{0, 1, 2, 3, 4, 5};
std::cout << "NumOddElements=" << GetCountIf(v, [](auto val) { return (val % 2 == 1); }) << '\n';
// std::cout << "NumElements=" << GetCountIf(v) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
只有在我GetCountIf()使用两个参数调用时,代码才会编译.如果我尝试仅传递1个参数,编译将失败并显示以下错误:
main.cpp:18:34:错误:没有匹配函数来调用'GetCountIf'std
:: cout <<"NumElements ="<< GetCountIf(v)<<'\n'; ^ ~~~~~~~~~ main.cpp:5:5:注意:候选模板被忽略:无法推断模板参数'UnaryPredicate'int GetCountIf(std :: vector v,UnaryPredicate pred = {return true;} ){^ 1生成错误.
当编译器遇到GetCountIf只有1个参数的调用时,为什么它不能推断出可选lambda的类型?如果我像这样明确指定谓词的类型,它可以工作:
template <typename T, class UnaryPredicate = std::function<bool(T)>>
int GetCountIf(std::vector<T> v, UnaryPredicate pred = [](T) { return true;}) {
...
}
Run Code Online (Sandbox Code Playgroud)
为什么这样做?
(我正在使用C++ 14)
注意,函数参数的默认值不会用于模板参数的模板参数推导; 这导致模板参数演绎失败,UnaryPredicate无法推导出类型.
请参阅非推断的上下文.
在下列情况下,用于组成P的类型,模板和非类型值不参与模板参数推导,而是使用在别处推导或显式指定的模板参数.如果模板参数仅在非推导的上下文中使用且未明确指定,则模板参数推断将失败.
4)在函数参数的参数类型中使用的模板参数,该参数具有在正在进行参数推断的调用中使用的默认参数:
Run Code Online (Sandbox Code Playgroud)template<typename T, typename F> void f(const std::vector<T>& v, const F& comp = std::less<T>()); std::vector<std::string> v(3); f(v); // P1 = const std::vector<T>&, A1 = std::vector<std::string> lvalue // P1/A1 deduced T = std::string // P2 = const F&, A2 = std::less<std::string> rvalue // P2 is non-deduced context for F (template parameter) used in the // parameter type (const F&) of the function parameter comp, // that has a default argument that is being used in the call f(v)
和
无法从函数默认参数的类型推导出类型模板参数:
Run Code Online (Sandbox Code Playgroud)template<typename T> void f(T = 5, T = 7); void g() { f(1); // OK: calls f<int>(1, 7) f(); // error: cannot deduce T f<int>(); // OK: calls f<int>(5, 7) }
另一方面,如果std::function<bool(T)>为template参数指定默认值UnaryPredicate,那么它将被用作UnaryPredicate如果UnaryPredicate未明确指定或不推导出参数for 的类型.
| 归档时间: |
|
| 查看次数: |
141 次 |
| 最近记录: |