C++ 按类型构造std::mem_fn
考虑这个人为的例子:C++ 按类型构造std::mem_fn,c++,c++11,c++14,C++,C++11,C++14,考虑这个人为的例子: template<typename Fn, typename Iter, typename T> void funny_transform(Iter first, Iter last, vector<T>& v) { transform(first, last, back_inserter(v), Fn()); } 这将不起作用,因为decltype(get\u size)(不
template<typename Fn, typename Iter, typename T>
void funny_transform(Iter first, Iter last, vector<T>& v)
{
transform(first, last,
back_inserter(v),
Fn());
}
这将不起作用,因为decltype(get\u size)
(不管它是什么)没有默认构造函数。奇怪的是,它有复制和移动构造函数。出于完全相同的原因,切换到简单的lambda也不起作用
我是否必须编写自己的functorstruct
来解决这个问题?是否有任何标准库工具可供我使用?模板
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); }
F&magic_商店(F*F){
静态常数fr=std::move(*F);
返回r;
}
模板
无状态结构{
无状态存储(F&&F){magic_存储(&F);}
无状态_t()=默认值;
模板
decltype(自动)运算符()(Args&&…Args)常量{
返回幻方存储(nullptr)(标准::转发(f));
}
};
模板
无状态\u t使\u无状态(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
auto get_size=make_无状态([](auto&s){return s.size();});
向量v1={…};
矢量v2;
有趣的_变换(v1.cbegin(),v1.cend(),v2);//作品
请注意,这是一个可怕的黑客,但标准的法律。它很容易被滥用,也很容易在非本地搞砸。仅对已无状态的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)... );
}
};
模板
结构无状态调用程序{
模板
decltype(自动)运算符()(Args&&…Args)常量{
返回std::invoke(F,std::forward(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
使用get\u size=stateless\u调用程序;
向量v1={…};
矢量v2;
有趣的_变换(v1.cbegin(),v1.cend(),v2);//作品
这就不那么麻烦了。这可以在C++11中复制,但很难看。基于@Yakk的想法,C++14中的一个简单解决方案可以如下所示:
template<typename PMF, PMF pmf>
struct my_mem_fn_t {
template<typename... Args>
constexpr decltype(auto) operator()(Args&&... args) const
noexcept(noexcept(std::mem_fn(pmf)(std::forward<Args>(args)...)))
{
return std::mem_fn(pmf)(std::forward<Args>(args)...);
}
};
// well, if you really want to use macro
#define my_mem_fn(pmf) my_mem_fn_t<decltype(pmf), pmf>()
模板
结构我的记忆{
模板
constexpr decltype(auto)运算符()(Args&&…Args)const
noexcept(noexcept(std::mem_fn(pmf)(std::forward(args)…))
{
返回std::mem_fn(pmf)(std::forward(args)…);
}
};
//如果你真的想用宏
#定义my_mem_fn(pmf)my_mem_fn_t()
然后:
auto get\u size=my\u mem\u fn\t;
//或者:my_mem_fn(&string::size);
字符串s(“你好”);
cout“std::map采用比较器的类型,而不是比较器对象。“Wat”和mem\u fn
返回的东西根据定义不是无状态的。@T.C.我应该说“std::map
可以采用比较器的类型并尝试默认构造它。”@T.C.为什么它不是无状态的?我认为可以使用纯无状态函子struct
来实现它。我可能错了。你为什么不试着写呢?@ziz看看C++17版本,它几乎没有那么邪恶。嗯,C++17版本看起来更合理。任何类型都可以绑定到自动F
?它是否与当前的非类型模板参数具有相同的约束?@ziz它有点像template
,但只是template
。如果它有更多的怪癖,我不知道,我还没有用过它你知道有没有一个编译器能够真正编译这个吗?我用-std=c++1z
尝试了gcc 6.1.0,但gcc无法识别语法。@ziz-nope。请参阅,以获取(已接受的功能完整草案)建议I基于的C++17版本。
template<typename PMF, PMF pmf>
struct my_mem_fn_t {
template<typename... Args>
constexpr decltype(auto) operator()(Args&&... args) const
noexcept(noexcept(std::mem_fn(pmf)(std::forward<Args>(args)...)))
{
return std::mem_fn(pmf)(std::forward<Args>(args)...);
}
};
// well, if you really want to use macro
#define my_mem_fn(pmf) my_mem_fn_t<decltype(pmf), pmf>()
auto get_size = my_mem_fn_t<decltype(&string::size), &string::size>;
// or: my_mem_fn(&string::size);
string s("hello");
cout << decltype(get_size)()(s) << '\n'; // prints 5