Phạ*_*ông 3 c++ templates type-deduction
我有两个模板方法
template <typename T, typename Ret, typename ...Args>
Ret apply(T* object, Ret(T::*method)(Args...), Args&& ...args) {
return (object->*method)(std::forward(args)...);
};
template <typename T, typename Ret, typename ...Args>
Ret apply(T* object, Ret(T::*method)(Args...) const, Args&& ...args) {
return (object->*method)(std::forward(args)...);
};
Run Code Online (Sandbox Code Playgroud)
我的目的是在这些args上应用T类的成员方法
这是我的测试代码:
int main() {
using map_type = std::map<std::string, int>;
map_type map;
map.insert(std::make_pair("a", 1));
std::cout << "Map size: " << apply(&map, &map_type::size) << std::endl; //this code work
apply(&map, &map_type::insert, std::make_pair("a", 1)); //failed to compile
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是编译器错误消息:
test.cpp: In function ‘int main()’:
test.cpp:61:58: error: no matching function for call to ‘apply(map_type*, <unresolved overloaded function type>, std::pair<const char*, int>)’
apply(&map, &map_type::insert, std::make_pair("a", 1));
^
test.cpp:11:5: note: candidate: template<class T, class Ret, class ... Args> Ret apply(T*, Ret (T::*)(Args ...), Args&& ...)
Ret apply(T* object, Ret(T::*method)(Args...), Args&& ...args) {
^~~~~
test.cpp:11:5: note: template argument deduction/substitution failed:
test.cpp:61:58: note: couldn't deduce template parameter ‘Ret’
apply(&map, &map_type::insert, std::make_pair("a", 1));
Run Code Online (Sandbox Code Playgroud)
std::map::insert是一个重载的功能.除非您明确指定您感兴趣的重载,否则您不能获取其地址 - 编译器还会知道什么?
解决问题的最简单方法是apply接受一个任意的函数对象,并将你的调用包装insert在一个通用的lambda中.
template <typename F, typename ...Args>
decltype(auto) apply(F f, Args&& ...args) {
return f(std::forward<Args>(args)...);
};
Run Code Online (Sandbox Code Playgroud)
用法:
::apply([&](auto&&... xs) -> decltype(auto)
{
return map.insert(std::forward<decltype(xs)>(xs)...);
}, std::make_pair("a", 1));
Run Code Online (Sandbox Code Playgroud)
遗憾的是,附加的语法样板是不可避免的.这可能在将来发生变化,请参阅:
我不确定上述提案是否支持重载的成员函数.
您也可以通过明确指定调用者方面遇到的重载来使用原始解决方案:
::apply<map_type, std::pair<typename map_type::iterator, bool>,
std::pair<const char* const, int>>(
&map, &map_type::insert<std::pair<const char* const, int>>,
std::make_pair("a", 1));
Run Code Online (Sandbox Code Playgroud)
你可以看到它不是很漂亮.它可以通过一些更好的模板参数推导来改进,但不是很多.