mac*_*ekp 4 c++ templates reference functor
我有一个仿函数f,它接受函数func和与func相同类型的参数t.由于编译错误(调用没有匹配函数),我无法将g传递给f f(int&, void (&)(int&)).如果g将采用非引用参数g(int s),则编译完成.或者,如果我手动指定模板参数f<int&>(i, g),编译也会完成.
template<typename T>
void f(T t, void (*func)(T)) {}
void g(int& s) {}
int main(int, char*[])
{
int i = 7;
f(i, g); // compilation error here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能获得演绎?
您可以像这样调用函数:
f<int&>(i, g);
Run Code Online (Sandbox Code Playgroud)
但现在我也将通过参考传递.
一般来说,我也将该函数设为模板类型:
template <typename T, typename F>
void f(T t, F func)
{
func(t); //e.g
}
Run Code Online (Sandbox Code Playgroud)
我想你需要:
void f(T t, void (*func)(T&)) {}
Run Code Online (Sandbox Code Playgroud)
要么:
void g(int s) {}
Run Code Online (Sandbox Code Playgroud)
但是我更喜欢:
template<typename T, typename T2>
void f(T t, T2 func) {}
Run Code Online (Sandbox Code Playgroud)
因为这将适用于函数和函子.
问题是如果在模板中,其中一个函数参数在推导开始之前不是引用类型,那么该参数将永远不会推导为引用类型.因此,在左侧的扣除中,T收益率int,但在右侧的扣除,T收益率int&.这是一个错误的匹配,编译器抱怨.
最好的方法是使函数参数与函数指针的参数类型相同:
template<typename T> struct identity { typedef T type; };
template<typename T>
void f(typename identity<T>::type t, void (*func)(T)) {}
Run Code Online (Sandbox Code Playgroud)
通过使用identity<T>::type,您可以禁用左侧的扣除.一旦T确定在右侧,将T被引入左侧并产生最终参数类型.
一个人建议将右侧作为模板参数 - 这是一件好事,因为它可以接受带有operator()重载的函数对象.但是你要面对的问题是必须知道它是否需要引用.为了解决这个问题,boost有reference_wrapper(顺便说一下,boost也有identity上面的模板).
template<typename T, typename F>
void f(T t, F func) {}
Run Code Online (Sandbox Code Playgroud)
现在,如果你想传递引用而不是副本,你可以这样做
int i;
f(boost::ref(i), some_function);
Run Code Online (Sandbox Code Playgroud)
ref返回一个可隐式转换为的reference_wrapper对象T&.因此,如果您调用func(t),t则会自动转换为目标引用.如果您不想传递引用,只需i直接传递即可.
| 归档时间: |
|
| 查看次数: |
1447 次 |
| 最近记录: |