我习惯于在函数指针中看到这样的语法
int (*pointer_name) (float, char *);
void call_function (void (*)(int), int);
Run Code Online (Sandbox Code Playgroud)
在一些C++ 03函数库中,我看到以这种方式使用的类型:
abc::function<void(*)(int,float)> f;
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,std::function我看到了这种方式给出的类型
std::function<void(int,float)> f;
Run Code Online (Sandbox Code Playgroud)
有一个失踪(*).为什么?
在C++ 03 function<T>已经T是相同的类型到相应的函数指针.很容易想象实现.
std::function在C++ 11中,核心语言增强功能支持它.是否已扩展模板参数类型以适应可调用性?
我已经定义了一个名为class的模板CallBackAtInit,其目的只是在初始化时调用一个函数(构造函数).该函数在模板参数中指定.问题是模板不接受std::function参数; 但他们接受函数指针.为什么?
这是我的代码:
#include <iostream>
#include <functional>
/* Does not work:*/ template <typename return_type, typename arg_type, std::function<return_type(arg_type)> call_back>
/* Work fine: */// template <typename return_type, typename arg_type, return_type(*call_back)(arg_type)>
class CallBackAtInit {
public:
CallBackAtInit(arg_type arg)
{
call_back(arg);
};
};
void printInt(int i);
class HoldInt : private CallBackAtInit<void, int, printInt> {
public:
HoldInt(int integer)
: CallBackAtInit(integer)
{}
// ...
};
int main(int argc, char** argv)
{
HoldInt hi(10);
return 0;
}
void printInt(int i)
{
std::cout << i …Run Code Online (Sandbox Code Playgroud) 我可以合法地在std::function(或其他类似的构造)中使用模板参数的名称吗?例如给出代码
std::function<int(int, int)> some_func;
Run Code Online (Sandbox Code Playgroud)
我可以按照以下方式重写吗?
std::function<int(int begin, int end)> some_func;
Run Code Online (Sandbox Code Playgroud)
如果它符合标准,那将是非常好的,因为单独的类型几乎没有关于参数目的的信息.
到目前为止,我已经在Visual Studio 2013中对它进行了测试,但它确实有效.编辑:它也适用于gcc 4.8.1.
首先,请考虑以下代码:
#include <iostream>
#include <functional>
struct Noisy
{
Noisy() { std::cout << "Noisy()" << std::endl; }
Noisy(const Noisy&) { std::cout << "Noisy(const Noisy&)" << std::endl; }
Noisy(Noisy&&) { std::cout << "Noisy(Noisy&&)" << std::endl; }
~Noisy() { std::cout << "~Noisy()" << std::endl; }
};
void foo(Noisy n)
{
std::cout << "foo(Noisy)" << std::endl;
}
int main()
{
Noisy n;
std::function<void(Noisy)> f = foo;
f(n);
}
Run Code Online (Sandbox Code Playgroud)
以及它在不同编译器中的输出:
Noisy()
Noisy(const Noisy&)
Noisy(Noisy&&)
foo(Noisy)
~Noisy()
~Noisy()
~Noisy()
Run Code Online (Sandbox Code Playgroud)
Noisy() …Run Code Online (Sandbox Code Playgroud) 如果我需要生成一个调用成员函数的lambda,我应该通过引用捕获还是捕获'this'?我的理解是'&'仅捕获使用的变量,但'this'捕获所有成员变量.那么使用'&'会更好吗?
class MyClass {
public:
int mFunc() {
// accesses member variables
}
std::function<int()> get() {
//return [this] () { return this->mFunc(); };
// or
//return [&] () { return this->mFunc(); };
}
private:
// member variables
}
Run Code Online (Sandbox Code Playgroud) 我目前有一个map<int, std::wstring>,但为了灵活性,我希望能够分配一个lambda表达式,std::wstring在地图中作为值返回.
所以我创建了这个模板类:
template <typename T>
class ValueOrFunction
{
private:
std::function<T()> m_func;
public:
ValueOrFunction() : m_func(std::function<T()>()) {}
ValueOrFunction(std::function<T()> func) : m_func(func) {}
T operator()() { return m_func(); }
ValueOrFunction& operator= (const T& other)
{
m_func = [other]() -> T { return other; };
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
并使用它像:
typedef ValueOrFunction<std::wstring> ConfigurationValue;
std::map<int, ConfigurationValue> mymap;
mymap[123] = ConfigurationValue([]() -> std::wstring { return L"test"; });
mymap[124] = L"blablabla";
std::wcout << mymap[123]().c_str() << std::endl; // outputs "test"
std::wcout << …Run Code Online (Sandbox Code Playgroud) 我有许多具有不同签名的回调函数.理想情况下,我想将它们放在一个向量中,并根据某些条件调用适当的一个.
例如
void func1(const std::string& value);
void func2(const std::string& value, int min, int max);
const std::vector<std::function<void(std::string)>> functions
{
func1,
func2,
};
Run Code Online (Sandbox Code Playgroud)
我意识到上述情况是不可能的,但我想知道是否有任何我应该考虑的替代方案.我还没有找到任何东西,我已经尝试过,std::bind但没有成功实现我想要的东西.
这样的事情可能吗?
首先,我定义了两个相互继承的类.
class A {
};
class B : public A {
};
Run Code Online (Sandbox Code Playgroud)
然后,我声明一个使用以下函数的函数std::function<void(A*)>:
void useCallback(std::function<void(A*)> myCallback);
最后,我std::function从我想要在回调函数中使用的其他地方收到一个不同的(但理论上兼容的)类型:
std::function<void(B*)> thisIsAGivenFunction;
useCallback(thisIsAGivenFunction);
Run Code Online (Sandbox Code Playgroud)
我的编译器(clang ++)拒绝这个,因为它的类型thisIsAGivenFunction与期望的类型不匹配.但是B继承自己A,接受它是有道理的thisIsAGivenFunction.
应该是吗?如果没有,为什么?如果它应该,那么我做错了什么?
如果函数返回一个引用但返回类型没有明确地作为引用调用,那么我在使用lambdas创建的std :: functions时遇到问题.似乎std :: function被创建没有警告,但是在调用它时,在预期引用时返回一个值,导致事情爆炸.这是一个非常人为的例子:
#include <iostream>
#include <vector>
#include <functional>
int main(){
std::vector<int> v;
v.push_back(123);
std::function<const std::vector<int>&(const std::vector<int>&)> callback =
[](const std::vector<int> &in){return in;};
std::cout << callback(v).at(0) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这会打印出垃圾,但是如果修改lambda以显式返回一个const引用,它就可以正常工作.我可以理解编译器认为lambda是没有提示的值返回值(当我最初遇到这个问题时,lambda直接从返回const引用的函数返回结果,在这种情况下我会认为lambda的const引用返回是可以推导的,但显然不是.)令我惊讶的是,编译器允许std :: function由具有不匹配返回类型的lambda构造.这种行为有望吗?我是否遗漏了标准中允许发生这种不匹配的内容?我用g ++(GCC)4.8.2看到这个,没有尝试过其他任何东西.
谢谢!
我std::function指着一个函数.在这个函数内部,我将指针更改为另一个函数.
std::function<void()> fun;
void foo() {
std::cout << "foo\n";
}
void bar() {
std::cout << "bar\n";
fun = foo;
}
int main() {
fun = bar;
fun();
fun();
}
Run Code Online (Sandbox Code Playgroud)
我看不出任何问题,它工作正常(见这里),但我不确定这是否合法.有什么我想念的吗?也许在c ++标准草案中(我快速检查但到目前为止没有看到任何内容).