带函数指针的模板推导还原
Template deduction reversion with function pointer
我以前的工作代码在从 g++-5 移动到 g++-6 时失败;先前可推导的模板不再可推导。一个最小的例子:
#include <math.h>
template<typename T,typename T1>
T apply(T (*func)(T1), const T1 &val)
{
return func(val);
}
int main(void)
{
double val1 = 0.5, val2 = apply(ceil,val1);
return 0;
}
g++-6 似乎找不到 ceil
的正确版本:
foo.cpp: In function ‘int main()’:
foo.cpp:11:44: error: no matching function for call to ‘apply(<unresolved overloaded function type>, double&)’
double val1 = 0.5, val2 = apply(ceil,val1);
^
foo.cpp:4:3: note: candidate: template<class T, class T1> T apply(T (*)(T), const T1&)
T apply(T (*func)(T), const T1 &val)
^~~~~
foo.cpp:4:3: note: template argument deduction/substitution failed:
foo.cpp:11:44: note: couldn't deduce template parameter ‘T’
double val1 = 0.5, val2 = apply(ceil,val1);
g++-5 没有问题并且按预期工作。在 https://godbolt.org/z/oBSopG 处使用带有 g++ 8 的编译器资源管理器,我还看到从 clang-3.3(编译)到 clang-3.4(不编译)的逆转。
鉴于代码仍然无法工作,即使在当前的 g++ 中,我认为错误是我的部分。我做错了什么,我该如何解决?
What have I done wrong and how can I fix it?
解决这个问题的方法是 #include <cmath>
而不是 reference documentation 中提到的 #include <math.h>
:
#include <cmath> // <<< official header to use.
#include <iostream>
template<typename T,typename T1>
T apply(T (*func)(T1), const T1 &val)
{
return func(val);
}
int main(void)
{
double val1 = 0.5, val2 = apply(ceil,val1);
std::cout << val1 << ' ' << val2<< std::endl;
}
如果您正在使用(或计划使用)C++17,您应该知道有一个更强大的库函数可以做您正在尝试做的事情:std::invoke
有了它,你的例子可以简化为:
#include <cmath>
#include <functional>
int main(void)
{
double val1 = 0.5, val2 = std::invoke(ceil,val1);
return 0;
}
有趣的是,对于您手工制作的 apply
和库 std::invoke
,如果您编写 std::invoke(std::ceil, val1)
,代码将失败。这需要进一步调查....
我以前的工作代码在从 g++-5 移动到 g++-6 时失败;先前可推导的模板不再可推导。一个最小的例子:
#include <math.h>
template<typename T,typename T1>
T apply(T (*func)(T1), const T1 &val)
{
return func(val);
}
int main(void)
{
double val1 = 0.5, val2 = apply(ceil,val1);
return 0;
}
g++-6 似乎找不到 ceil
的正确版本:
foo.cpp: In function ‘int main()’:
foo.cpp:11:44: error: no matching function for call to ‘apply(<unresolved overloaded function type>, double&)’
double val1 = 0.5, val2 = apply(ceil,val1);
^
foo.cpp:4:3: note: candidate: template<class T, class T1> T apply(T (*)(T), const T1&)
T apply(T (*func)(T), const T1 &val)
^~~~~
foo.cpp:4:3: note: template argument deduction/substitution failed:
foo.cpp:11:44: note: couldn't deduce template parameter ‘T’
double val1 = 0.5, val2 = apply(ceil,val1);
g++-5 没有问题并且按预期工作。在 https://godbolt.org/z/oBSopG 处使用带有 g++ 8 的编译器资源管理器,我还看到从 clang-3.3(编译)到 clang-3.4(不编译)的逆转。
鉴于代码仍然无法工作,即使在当前的 g++ 中,我认为错误是我的部分。我做错了什么,我该如何解决?
What have I done wrong and how can I fix it?
解决这个问题的方法是 #include <cmath>
而不是 reference documentation 中提到的 #include <math.h>
:
#include <cmath> // <<< official header to use.
#include <iostream>
template<typename T,typename T1>
T apply(T (*func)(T1), const T1 &val)
{
return func(val);
}
int main(void)
{
double val1 = 0.5, val2 = apply(ceil,val1);
std::cout << val1 << ' ' << val2<< std::endl;
}
如果您正在使用(或计划使用)C++17,您应该知道有一个更强大的库函数可以做您正在尝试做的事情:std::invoke
有了它,你的例子可以简化为:
#include <cmath>
#include <functional>
int main(void)
{
double val1 = 0.5, val2 = std::invoke(ceil,val1);
return 0;
}
有趣的是,对于您手工制作的 apply
和库 std::invoke
,如果您编写 std::invoke(std::ceil, val1)
,代码将失败。这需要进一步调查....