为什么我会收到此错误?无法从<brace-enclosed initializer =“”list =“”>转换为&#39; std :: vector&lt;&gt;&#39;

时间:2016-04-19 13:33:12

标签: c++ c++11

我正在使用支持C ++ 11的ARM微控制器和编译器

我的课程描述如下:

class commands 
{
public:
    string cmd_str;
    void (*fktPtr)(void);
};

diag对象是Diag Class的一部分

class Diag
{
public:
void reset(void);
}

Diag diag;

切换功能是代码中的独立功能:

void toggle_pin(void);

然后我定义了一个名为cmdlist的命令向量:

vector<commands> cmdlist = {

{"togg",     toggle_pin }, // this works
{"rst",      diag.reset}, // this gives an error. why ?
{"rst1",     [](){diag.reset();}}, // this also works
}

错误:

main.cpp:81:1: error: could not convert '{{"togg", toggle_pin}, {"rst", diag.Diag::reset}}, {"rst1",<lambda closure object><lambda()>{}} from '<brace-enclosed initializer list>' to 'std::vector<commands>'

为什么没有来自对象的初始化列表支持方法,但是支持常规函数/ lambda函数?

1 个答案:

答案 0 :(得分:5)

它与初始化列表或向量无关,您可以从

获得相同的错误
void (*fktPtr)(void) = diag.reset;

你有两个问题,一个是缺少&来创建一个函数指针。裸函数隐式转换为函数指针;成员函数没有这样的转换。

那么我们就有了:

void (*fktPtr1)(void) = &toggle_pin; // works
void (*fktPtr2)(void) = &Diag::reset; // doesn't

现在,您遇到了类型不兼容的问题。非静态成员函数的地址具有类型指向成员函数的指针,与裸函数和静态成员函数不同(这些函数仍然需要显式&ClassName::FunctionName,但产生正常的函数指针)。您无法将指向成员的指针转换为普通函数指针。

部分问题是指向成员的函数需要一个目标对象(有时称为隐藏this参数)。提前设置C ++的方法是std::bind,但你仍然没有得到普通的函数指针。

lambda导致一个普通的函数(指针最终在你的向量中),它从全局变量中检索目标对象并在其上调用一个函数。这是合法的,但可能根本没有类,因为你被锁定到全局变量命名的单个实例。

如果您想要更接近C#等语言中的“委托”,将函数和目标对象存储在一起,请尝试

std::function<void (void)> fktPtr;

而不是裸函数指针。这与裸函数,静态成员函数,绑定实例成员函数,非捕获lambdas和捕获lambda都兼容。