考虑以下计划。我使用h()
作为帮助来解决带有指向cmath中重载函数的指针的歧义:
#include <cmath>
typedef double(*PF1)(double);
typedef double(*PF2)(double, double);
typedef double(*PF3)(double, double, double);
// etc...
auto h(PF1 p) -> decltype(p) {return p;}
auto h(PF2 p) -> decltype(p) {return p;}
auto h(PF3 p) -> decltype(p) {return p;}
int f(int) {return 0;}; // my math function
int main() {
//auto s_ = std::sin; // won't work as std::sin is overloaded
auto s = h(std::sin); // works, type of s is a double(*)(double)
auto p = h(std::pow); // OK.
// auto my_aim = h(f); // my aim is to make h() work with f too
}
在给定指向函数本身的指针的情况下,是否有更智能或更通用的帮助器来减去指向(可能的)重载函数的指针的类型,因此推导将“更喜欢”仅包含双重类型的重载(如果可用,则返回类型和参数;否则返回其他重载之一。
答案 0 :(得分:3)
以下内容可能有所帮助:
constexpr auto h(double(*p)(double)) -> decltype(p) {return p;}
constexpr auto h(double(*p)(double, double)) -> decltype(p) {return p;}
constexpr auto h(double(*p)(double, double, double)) -> decltype(p) {return p;}
template <typename Return, typename ... Args>
constexpr auto h(Return (*p)(Args...)) -> decltype(p) {return p;}
int f(int) {return 0;}; // my math function
int main(int argc, char *argv[])
{
//auto s_ = std::sin; // won't work as std::sin is overloaded
auto s = h(std::sin); // works, type of s is a double(*)(double)
auto p = h(std::pow); // OK.
auto my_aim = h(f); // works too
return 0;
}
只要提供h
个double(*p)(double..)
个参数(或f
)或没有重载(对于template<typename Sign, typename ... Signs>
struct identity : identity<Signs...>
{
using identity<Signs...>::h;
static constexpr auto h(Sign p) -> decltype(p) {return p;}
};
template<typename Sign>
struct identity<Sign>
{
static constexpr auto h(Sign p) -> decltype(p) {return p;}
template <typename T>
static constexpr auto h(T p) -> decltype(p) {return p;}
};
)(因此模板可以推断其类型)。
修改强>
添加一个更通用的类来处理:
typedef identity<double(*)(double),
double(*)(double, double),
double(*)(double, double, double)> MyIdentity;
int f(int) {return 0;}; // my math function
int main(int argc, char *argv[])
{
auto s = MyIdentity::h(std::sin); // works : double(*)(double)
auto p = MyIdentity::h(pow); // works : double(*)(double, double)
auto my_aim = MyIdentity::h(f); // works : (int)(*)(int)
return 0;
}
让我们在你的例子中使用它:
{{1}}
答案 1 :(得分:0)
这是我最接近你想要做的事情:
#include <cmath>
#include <functional>
template<typename R, typename ...A>
auto h(R f(A...)) -> std::function<R(A...)>
{
return std::function<R(A...)>(f);
}
int main() {
auto s = h<double, double>(std::sin);
auto p = h<double, double, double>(std::pow);
}
您仍然需要指定要传入的函数的返回类型和参数,但这是因为如果不指定重载,它将是不明确的。
如果你有一个推导出的参数明确无误的函数,那就是:
int only_one_overload(int a, int b) {
return a + b;
}
auto x = h(only_one_overload);
我建议只使用函数指针:
double (*s)(double) = std::sin;
double (*p)(double, double) = std::pow;
答案 2 :(得分:0)
Boost库有Boost.Functional/OverloadedFunction库,它被分配以将不同的重载包装到单个函数对象中:
boost::overloaded_function<
const std::string& (const std::string&)
, int (int)
, double (double)
> identity(identity_s, identity_i, identity_d);
// All calls via single `identity` function.
BOOST_TEST(identity("abc") == "abc");
BOOST_TEST(identity(123) == 123);
BOOST_TEST(identity(1.23) == 1.23);
我认为使用此库可以轻松解决您的问题。即使这个解决方案没有直接回答你的问题,我认为使用boost::overloaded_function
是一种更好的方法将不同的函数绑定到一个对象中,只通过一个对象调用不同的函数,这是你的最终目标,不是吗? (我已按照您之前提出的问题推断出)。