C++11 以std::function<void()> 做非类型模板的参数类型为什么会报错呢?
迷茫
迷茫 2017-04-17 11:38:24
0
2
586

正在学习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除了能包装匿名函数外,还有什么情况下与函数对象或者普通函数指针表现不同呢?谢谢。

迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

reply all(2)
黄舟

Because non-type template arguments must be constant expressions. Because everything in the template must be determined at compile time.
http://en.cppreference.com/w/...

Non-type template parameter type is one of the following types (optionally cv-qualified, the qualifiers are ignored)

  1. integral type

  2. enumeration

  3. pointer to object or to function

  4. lvalue reference to object or to function

  5. pointer to member object or to member function

  6. std::nullptr_t (since C++11)

wrapper<f>() where f is a variable, its value can only be determined during runtime. So the template cannot be compiled and passed. You can't wait until runtime and then Instantiate a wrapper<f> function and let i point to f, right?

For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values)., so <void i()> can compile and pass:

template <typename std::function<void()> *i>
void wrapper() {
  (*i)();
}

// 将static 换成 extern 才能通过 MS C++
static std::function<void()> f=hello;
int main() {
  wrapper<&f>(); // G++ OK

  //下面的不行
  constexpr std::function<void()> *f3=&f;
  wrapper<f3>();

  //顺便说,下面也能编译成功,只是运行当然是segmentfault啦
  constexpr std::function<void()> *f2=0;
  wrapper<f2>();
  return 0;
}
伊谢尔伦

The way you write it, template < std::function<void()> i >, here i is obviously a variable, not a type. If you want to declare a type, you should write it as template <typename Func>. However, if it is declared as a type, wrapper will of course not work, because i() is equivalent to instantiating an empty std::function object and does nothing. In the end, of course, you will not get the effect you want.

Generally speaking, you should implement wrapper like this to be normal.

template <typename Func>
void wrapper(Func func) {
    func();
}
The biggest function of

std::function is to express anonymous functions, especially the anonymous functions in [] that capture the current context variables. When used together with std::shared_ptr, it will give the illusion of a dynamic language.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!