由于常量不一致导致模板参数推导失败
Template argument deduction failure due to inconsistent constness
请考虑以下内容(doesn't compile,但我们稍后会解决):
void foo(const int *n) { }
template <typename ...Args>
void bar(void (*func)(Args...), Args... args) { func(args...); }
int main(int argc, char *argv[])
{
int n = 42;
bar(foo, &n);
}
模板函数bar()
接受一个函数指针来调用和传递给它的参数包。 gcc 7.4.0 诊断出以下错误:
test.cpp:6:6: note: template argument deduction/substitution failed:
test.cpp:11:16: note: inconsistent parameter pack deduction with ‘const int*’ and ‘int*’
很明显,type deduction rules are not relaxed enough to allow const T*
to be deduced when both const T*
and T*
are observed. OK, fine. This is easy enough to fix with a cast:
bar(foo, static_cast<const int *>(&n));
但这很丑陋。 C++17 有 std::as_const()
这使得它不那么难看 (&std::as_const(n)
) 但在我当前的项目中我仅限于 C++14,sadface.
Q: 有没有办法重新排列这段代码,这样类型推导就可以成功,而无需显式指定 bar()
的模板参数,也无需强制转换来解决不明确的 constness ?跳出框框思考是允许的,只要我可以将函数指针及其参数传递给模板函数!
函数指针和参数的推导可以分开:
void foo(const int *n) {}
template <typename... FArgs, typename... Args>
void bar(void (*func)(FArgs...), Args&&... args) {
func(std::forward<Args>(args)...);
}
int main(int argc, char *argv[]) {
int n = 42;
bar(foo, &n);
}
但那时我想知道为什么函数指针需要分解。为什么不接受任何调用?
void foo(const int *n) {}
template <typename F, typename... Args>
void bar(F func, Args&&... args) {
func(std::forward<Args>(args)...);
}
int main(int argc, char *argv[]) {
int n = 42;
bar(foo, static_cast<const int *>(&n));
bar([](int const*){}, &n);
}
此外,请记住 C++17 提供 std::invoke
:
std::invoke(foo, &n);
请考虑以下内容(doesn't compile,但我们稍后会解决):
void foo(const int *n) { }
template <typename ...Args>
void bar(void (*func)(Args...), Args... args) { func(args...); }
int main(int argc, char *argv[])
{
int n = 42;
bar(foo, &n);
}
模板函数bar()
接受一个函数指针来调用和传递给它的参数包。 gcc 7.4.0 诊断出以下错误:
test.cpp:6:6: note: template argument deduction/substitution failed:
test.cpp:11:16: note: inconsistent parameter pack deduction with ‘const int*’ and ‘int*’
很明显,type deduction rules are not relaxed enough to allow const T*
to be deduced when both const T*
and T*
are observed. OK, fine. This is easy enough to fix with a cast:
bar(foo, static_cast<const int *>(&n));
但这很丑陋。 C++17 有 std::as_const()
这使得它不那么难看 (&std::as_const(n)
) 但在我当前的项目中我仅限于 C++14,sadface.
Q: 有没有办法重新排列这段代码,这样类型推导就可以成功,而无需显式指定 bar()
的模板参数,也无需强制转换来解决不明确的 constness ?跳出框框思考是允许的,只要我可以将函数指针及其参数传递给模板函数!
函数指针和参数的推导可以分开:
void foo(const int *n) {}
template <typename... FArgs, typename... Args>
void bar(void (*func)(FArgs...), Args&&... args) {
func(std::forward<Args>(args)...);
}
int main(int argc, char *argv[]) {
int n = 42;
bar(foo, &n);
}
但那时我想知道为什么函数指针需要分解。为什么不接受任何调用?
void foo(const int *n) {}
template <typename F, typename... Args>
void bar(F func, Args&&... args) {
func(std::forward<Args>(args)...);
}
int main(int argc, char *argv[]) {
int n = 42;
bar(foo, static_cast<const int *>(&n));
bar([](int const*){}, &n);
}
此外,请记住 C++17 提供 std::invoke
:
std::invoke(foo, &n);