正在学习C++11的新特性,用非类型模板写了一个函数包装器,我是这样写的:
#include <iostream>
#include <cstdlib>
#include <string>
#include <functional>
void hello() {
std::cout << "Hello, world!\n";
return;
}
template< std::function<void()> i>
void wrapper() {
i();
}
int main() {
std::function<void()> f = hello;
wrapper<f>();
return 0;
}
在VS2013上编译错误,提示是
“std::function”: 非类型模板参数“i”的类型非法
但是当我将wrapper的定义改成
template<void i()>
void wrapper() {
i();
}
将调用改成wrapper<hello>();
之后编译运行就一切正常了。请问这是什么原因?
另外请问std::function除了能包装匿名函数外,还有什么情况下与函数对象或者普通函数指针表现不同呢?谢谢。
因为非类型模板实参必须是常量表达式。因为模板中的东西都必须是可在编译期确定的。
http://en.cppreference.com/w/...
wrapper<f>()
中 f是一个变量,它的值是运行期才能确定的。所以模板没办法编译通过,总不能等到运行时再Instantiate出一个wrapper<f>
函数,让其中的i指向f吧?For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values).,所以
<void i()>
可以编译通过:你的写法,
template < std::function<void()> i >
,这里的i
明显是一个变量,而不是类型,如果要声明类型应该写成template <typename Func>
。不过如果声明为类型,wrapper
当然就没法工作了,因为i()
就相当于实例化一个空的std::function
对象,并没有做任何事情,最终当然就不能得到你想要的效果。一般来说,你应该这样实现
wrapper
才正常。std::function
最大的功能是表达匿名函数,特别是[]
里面捕捉了当前上下文变量的匿名函数,结合着std::shared_ptr
一起用,会有一种动态语言的错觉。