为什么我不能创建带有可选 UnaryPredicate 参数的模板函数?
Why can't I create a template function with an optional UnaryPredicate argument?
我正在尝试创建一个带有可选参数的模板化函数,但我无法理解编译失败的原因。这是我的测试(设计)代码:
#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';
}
仅当我使用两个参数调用 GetCountIf()
时,代码才能编译。如果我尝试只向它传递 1 个参数,编译将失败并出现此错误:
main.cpp:18:34: error: no matching function for call to 'GetCountIf'
std::cout << "NumElements=" << GetCountIf(v) << '\n';
^~~~~~~~~~ main.cpp:5:5: note: candidate template ignored: couldn't infer template argument
'UnaryPredicate' int GetCountIf(std::vector v, UnaryPredicate
pred = { return true; }) {
^ 1 error generated.
当编译器遇到只有 1 个参数的 GetCountIf
调用时,为什么它无法推断出可选 lambda 的类型?如果我像这样明确指定谓词的类型,它会起作用:
template <typename T, class UnaryPredicate = std::function<bool(T)>>
int GetCountIf(std::vector<T> v, UnaryPredicate pred = [](T) { return true;}) {
...
}
为什么这样做?
(我使用的是 C++14)
注意函数参数的默认值不会用于模板参数的模板实参推导;导致模板参数推导失败,无法推导UnaryPredicate
的类型。
In the following cases, the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
4) A template parameter used in the parameter type of a function
parameter that has a default argument that is being used in the call
for which argument deduction is being done:
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)
和
Type template parameter cannot be deduced from the type of a function
default argument:
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)
}
另一方面,如果您为模板参数 UnaryPredicate
指定了默认值 std::function<bool(T)>
,那么它将被用作 UnaryPredicate
的类型,如果 UnaryPredicate
未明确指定或无法推断。
默认参数确实参与类型的推导,因此您观察到的行为。
作为替代方案,您可以创建重载:
template <class UnaryPredicate>
int GetCountIf(const std::vector<int>& v, UnaryPredicate pred) {
int count = 0;
for (auto i: v) {
if (pred(i)) {
count++;
}
}
return count;
}
int GetCountIf(const std::vector<int>& v) {
return GetCountIf(v, [](auto) { return true; }); // return v.size(); // :-)
}
我正在尝试创建一个带有可选参数的模板化函数,但我无法理解编译失败的原因。这是我的测试(设计)代码:
#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';
}
仅当我使用两个参数调用 GetCountIf()
时,代码才能编译。如果我尝试只向它传递 1 个参数,编译将失败并出现此错误:
main.cpp:18:34: error: no matching function for call to 'GetCountIf'
std::cout << "NumElements=" << GetCountIf(v) << '\n'; ^~~~~~~~~~ main.cpp:5:5: note: candidate template ignored: couldn't infer template argument 'UnaryPredicate' int GetCountIf(std::vector v, UnaryPredicate pred = { return true; }) { ^ 1 error generated.
当编译器遇到只有 1 个参数的 GetCountIf
调用时,为什么它无法推断出可选 lambda 的类型?如果我像这样明确指定谓词的类型,它会起作用:
template <typename T, class UnaryPredicate = std::function<bool(T)>>
int GetCountIf(std::vector<T> v, UnaryPredicate pred = [](T) { return true;}) {
...
}
为什么这样做?
(我使用的是 C++14)
注意函数参数的默认值不会用于模板参数的模板实参推导;导致模板参数推导失败,无法推导UnaryPredicate
的类型。
In the following cases, the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
4) A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done:
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)
和
Type template parameter cannot be deduced from the type of a function default argument:
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) }
另一方面,如果您为模板参数 UnaryPredicate
指定了默认值 std::function<bool(T)>
,那么它将被用作 UnaryPredicate
的类型,如果 UnaryPredicate
未明确指定或无法推断。
默认参数确实参与类型的推导,因此您观察到的行为。
作为替代方案,您可以创建重载:
template <class UnaryPredicate>
int GetCountIf(const std::vector<int>& v, UnaryPredicate pred) {
int count = 0;
for (auto i: v) {
if (pred(i)) {
count++;
}
}
return count;
}
int GetCountIf(const std::vector<int>& v) {
return GetCountIf(v, [](auto) { return true; }); // return v.size(); // :-)
}