我正在尝试创建模板仿函数,它将使用任意数量的参数作为参数对象和成员函数。我无法弄清楚如何使用模板正确编写代码。
template<typename ItemT,
class T,
typename ...Args>
struct Builder
{
ItemT operator()(T& object, ItemT (T::*method)(Args...), Args && ... args)
{
return (object.*method)(std::forward<Args>(args)...);
}
};
struct Object
{
int method(int, int, int) { return 4; }
};
int main()
{
Object obj;
Builder<int, Object>()(obj, &Object::method); // Error here
}
如果我使用没有参数的Object ::方法 - 代码编译。但有参数 - 没有。
严重级代码描述项目文件行抑制状态 错误C2664'int Builder :: operator()(T&amp;,ItemT(__ thishisall Object :: *)(void))':无法从'int(__thiscall Object :: *)(int,int,int)转换参数2 'to'int(__ thiscall Object :: *)(void)'草稿c:\ drafts \ main.cpp 139
答案 0 :(得分:4)
假设您不想更改import React, {PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {asyncConnect} from 'redux-async-connect';
import {load, isLoaded} from 'redux/modules/viewlodging';
@asyncConnect([{
promise: ({
store: {
dispatch,
getState
}
}) => {
const promises = [];
if (!isLoaded(getState())) {
promises.push(dispatch(load()));
}
return Promise.all(promises);
}
}])
@connect(
state => ({
viewdata: state.viewlodging.data
}),
dispatch => bindActionCreators({
load
}, dispatch)
)
export default class Product extends React.Component {
static propTypes = {
viewdata: PropTypes.object,
location: PropTypes.object,
load: PropTypes.func.isRequired
}
componentDidMount(){
const {id} = this.props.params;
this.props.load(id); //you can send params values after component get mounted.
}
render() {
console.log(this.props.routeParams.id); // here I get routeparameter
//don't send in render method, since it'll be called many times
const {
viewdata
} = this.props;
return ( < div >
< div > Sample test < /div> < /div> < Footer / >
< Viewfootertext viewdata = {
viewdata
}
/> < /div>
);
}
}
的当前定义,您需要实例化它:
Builder
Builder<int, Object, int, int, int>()(obj, &Object::method, 0, 0, 0);
// ^ ^ ^^^^^^^^^^^^^ ^^^^^^^
// ItemT | | |
// T Args... args...
调用中的args...
参数展开必须与传递给operator()
的{{1}}包一致。
这是另一种不太严格的设计:
TArgs...
以上Builder
可以这样使用:
template<typename T>
struct Builder
{
template <typename TFnPtr, typename... Args>
auto operator()(T& object, TFnPtr method, Args && ... args)
{
return (object.*method)(std::forward<Args>(args)...);
}
};
在这种情况下,成员函数指针的类型是通过Builder
推导出来的,并不限于任何特定的参数集。可变参数不再是int main()
{
Object obj;
Builder<Object>()(obj, &Object::method, 0, 0, 0);
}
的一部分 - 它们属于TFnPtr
的一部分,因此可以推导出它们并转发给Builder
。
答案 1 :(得分:1)
您可以完全避免在Builder
上进行模板操作,并且完全依赖于模板参数推断:
struct Builder {
template <typename Obj, typename R, typename ... FArgs, typename ... Args>
R operator()(Obj& obj, R (Obj::*fn)(FArgs...), Args&&... args) {
return (obj.*fn)(std::forward<Args>(args)...);
}
};
我选择使用两个参数包来实现完美转发:operator()
调用的值类别不一定与目标方法匹配。这也允许在应用成员函数指针时隐式转换参数。请注意,此实现与const
的{{1}}方法不匹配。
你当然可以使用Obj
返回类型(C ++ 14)或尾随返回类型(C ++ 11)来放松一下。由于Vittorio的答案已经向您呈现了C ++ 14方式,我将解决后者问题。然后auto
变为:
operator()
然后,用法只是:
template <typename Obj, typename FnPtr, typename ... Args>
auto operator()(Obj& obj, FnPtr fn, Args&&... args)
-> decltype((obj.*fn)(std::forward<Args>(args)...)) {
return (obj.*fn)(std::forward<Args>(args)...);
}
Coliru上的