gpt4 book ai didi

c++ - 按类型构造一个 std::mem_fn

转载 作者:太空狗 更新时间:2023-10-29 22:58:59 27 4
gpt4 key购买 nike

考虑这个人为的例子:

template<typename Fn, typename Iter, typename T>
void funny_transform(Iter first, Iter last, vector<T>& v)
{
transform(first, last,
back_inserter(v),
Fn());
}

通常我们会直接传入仿函数对象,但这个例子是为了模拟许多 STL 容器的行为而设计的。例如,std::map 可以采用比较器的 type 并默认构造它,而不是直接采用比较器对象。 (我的实际用例是一些无状态仿函数类。由于该类是无状态的,所以我只能传入类型。)

问题出在 std::mem_fn 上。如果我尝试做类似的事情:

auto get_size = mem_fn(&string::size);

vector<string> v1 = { ... };
vector<string::size_type> v2;

funny_transform<decltype(get_size)>(v1.cbegin(), v1.cend(), v2); // oops

这行不通,因为 decltype(get_size)(不管它是什么)没有默认构造函数。虽然奇怪它有复制和移动构造函数。出于完全相同的原因,切换到简单的 lambda 也不起作用。

我是否必须编写自己的仿函数 struct 来解决这个问题?有没有我可以使用的标准库工具?

最佳答案

template<class F>
F& magic_store(F* f) {
static const F r=std::move(*f);
return r;
}
template<class F>
struct stateless_t{
stateless_t(F&&f){ magic_store<F>(&f); }
stateless_t()=default;

template<class...Args>
decltype(auto) operator()(Args&&...args)const{
return magic_store<F>(nullptr)(std::forward<F>(f));
}
};
template<class F>
stateless_t<F> make_stateless(F f){ return std::move(f); }

现在你可以做

auto get_size = make_stateless([](auto&s){return s.size();});

vector<string> v1 = { ... };
vector<string::size_type> v2;

funny_transform<decltype(get_size)>(v1.cbegin(), v1.cend(), v2); // works

请注意,这是一个可怕的 hack,但标准合法。它很容易被滥用,也很容易在非本地搞砸。仅将它与已经无状态的 lambda 一起使用。从来没有任何东西


在 C++17 中你可以这样写:

template<auto F>
struct stateless_invoker{
template<class...Args>
decltype(auto) operator()(Args&&...args) const{
return std::invoke( F, std::forward<Args>(args)... );
}
};

它给你:

using get_size = stateless_invoker<&std::string::size>;

vector<string> v1 = { ... };
vector<string::size_type> v2;

funny_transform<get_size>(v1.cbegin(), v1.cend(), v2); // works

这不那么骇人听闻。这可以在 C++11 中重现,但很难看。

关于c++ - 按类型构造一个 std::mem_fn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38338926/

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