功能指针参数参数转换为const



示例代码:

class Foo;
typedef void (*fnptr)(Foo &foo);
fnptr gFn;
void myfoo(const Foo &foo) {}
int main() {
    gFn = &myfoo;
}

使用clang的错误失败:

main.cpp:9:9: error: assigning to 'fnptr' (aka 'void (*)(Foo &)') from incompatible type
      'void (*)(const Foo &)': type mismatch at 1st parameter ('Foo &' vs 'const Foo &')
    gFn = &myfoo;
        ^ ~~~~~~
1 error generated.

GCC也出于类似的错误而失败。传递指针而不是参考

我不太了解为什么这是一个错误。接受const foo&也接受foo&作为参数,在这两种情况下,指针都被传递了。我想了解为什么这是一个错误。

签名 void(*)(const Foo&)的函数是void(*)(Foo&)相同。

例如,您可以将rvalues传递给void myfoo(const Foo&),但是您不能使用void myfoo(Foo&)。因为,您知道,可以在呼叫站点的函数上检查可以通过的限制。

为了理智,还检查了这些约束。

示例:

class Foo{};
using FooPtr = void(*)(Foo&);
using ConstFooPtr = void(*)(const Foo&);
void fooNonConst(Foo&) { }
void fooConst(const Foo&) { }

int main() {
    FooPtr ptr1 = &fooNonConst;
    ConstFooPtr ptr2 = &fooConst;
    ptr1(Foo{});   //Not OK
    ptr2(Foo{});   //Ok
}

原因只是,因为标准要求它。为什么我们在我们的右边和英国的左边开车?好的开玩笑,但没有那么多。这样的角落有很多,我们发现自己在思考,但是为什么他们不允许这样做呢?有时,在下一个标准版本中不允许使用的内容。例如,在C 98中,只能在类声明中初始化静态常量积分成员,所有其他成员都应在构造函数中初始化。C 11允许在类声明中初始化成员。

但是,您所要求的可能会使编译器的类型安全控制更难,而它们已经很复杂了!

因此,在此处使用myfoo围绕包装器的一致程序的方法:

void myfoo_wrap(Foo &foo) {
    myfoo(foo);
}

我必须承认这看起来可能很愚蠢,但是好消息是优化编译器应该能够从可执行文件中删除它。这意味着这在源中是精简版,并且在可执行文件中不明显:恐怕该规则不会在标准中很快更改...

相关内容

最新更新