作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是一个看起来像这样的类:
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 formerstd::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/
我是一名优秀的程序员,十分优秀!