gpt4 book ai didi

c++ - 根据形参函数实参类型重载函数模板

转载 作者:行者123 更新时间:2023-11-30 05:29:01 26 4
gpt4 key购买 nike

我是一个看起来像这样的类:

template<typename A>
struct List {
...
template<typename Fn, typename B = typename std::result_of<Fn(A)>::type>
List<B> map(Fn f) const
{ ... }
};

我正在尝试重载 map 并允许它接受类型为 A 的 getter 作为参数,这样我们就可以执行 foos.map(&Foo::bar),其中 bar 是类 Foo 的 getter。以下功能有效:

template<typename Fn, typename B = typename std::result_of<Fn(A*)>::type>
List<B> mapGet(Fn getter) const
{ ... }

但是如果我尝试使用相同的名称 map,编译器会提示它不明确。我的问题是,当 Fn 是一个 getter 时,以前的 std::result_of 不会失败,有效地禁用其中一个重载的 map 吗?另外,有什么方法可以使重载成为可能吗?

最佳答案

My question is, when Fn is a getter wouldn't the former std::result_of fail, effectively disabling one of the overloaded maps?

我猜你说的“getter”是指指向成员函数的指针?在这种情况下,std::result_of 可以很好地处理它们。假设我们有一些类型 Foo:

struct Foo {
Foo(int i) : i(i) { }
int bar() const { return i; }
int i;
};

您可以像预期的那样使用指向成员的指针:

using T = std::result_of_t<decltype(&Foo::bar)(Foo )>;
static_assert(std::is_same<T, int>{}, "!");

唯一的区别是您实际调用 f 的方式。对于 C++17,有 std::invoke()这将适用于所有可调用类型,否则您可以直接使用 std::bind() 或编写您自己的包装器来做同样的事情。

举个例子,忽略复制、转发和保留,我们可以这样写 map:

template <class A, class F, class B = std::result_of_t<F(A)>>
std::vector<B> map(std::vector<A> xs, F f)
{
auto binder = std::bind(f, std::placeholders::_1);

std::vector<B> r;
for (auto& x : xs) {
r.push_back(binder(x));
}
return r;
}

这对实际的函数对象同样适用:

std::vector<int> vs{1, 2, 3, 4, 5};
std::vector<double> ds = map(vs, [](int i){return i * 2.0; });

就像我们的 Foo 一样,它带有指向成员的指针:

std::vector<Foo> foos{1, 2, 3, 4, 5};
std::vector<int> is = map(foos, &Foo::bar);

关于c++ - 根据形参函数实参类型重载函数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36580399/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com