c++ - 为什么 std::function 没有进行类型检查?

标签 c++ function c++11 c++17 std-function

#include <functional>

void toggleOk(bool& b) { b = !b; }
void toggleBroken(bool b) { b = !b; }
void toggleInt(int i) { i = !i; }
void tooManyParams(bool b, int i) { i = !b; }

int main()
{
    typedef std::function<void(bool&)> CallbackType;
    typedef std::function<void(bool)> WrongCallbackType;

    CallbackType cb1 = [](bool b) { b = !b; }; // Should throw error - missing reference
    CallbackType cb2 = toggleOk; // Ok

    CallbackType cb3 = toggleBroken; // Should throw error - missing reference
    CallbackType cb4 = toggleInt; // Should throw error - integer instead of bool

    WrongCallbackType cb5 = toggleBroken; // Ok

    CallbackType cb6 = cb5; // Type checking not even applying between std::functions

    CallbackType cb7 = tooManyParams; // Only this statement throws error

    return 0;
}
考虑上面的例子,它创建了一堆具有 的回调。引用 bool作为参数。除了最后一次回调 cb7 ,即使存储在回调对象中的大多数函数与 不匹配,此代码也可以很好地编译和运行。引用 类型 的参数。
我遇到过这种行为 VS19/C++20将 lambda 存储在 std::function 中,但是我已经用两个不同的 Windows G++ 编译器尝试了这个例子,启用了额外的诊断和 C++17/C++2a甚至没有人报告警告。
我的问题是 - 这是预期的行为还是错误?为什么?

最佳答案

是的,这是来自 std::function 的定义行为std::function使用 type erasure mechanism扭曲几乎所有类型的可调用对象,并参数化为非常量、非引用、非 volatile 参数和可调用对象的返回类型。
您需要使用平面类型函数指针来获取代码中的预期错误

void toggleOk(bool& b) { b = !b; }
void toggleBroken(bool b) { b = !b; }
void toggleInt(int i) { i = !i; }
void tooManyParams(bool b, int i) { i = !b; }

int main()
{
    // typedef std::function<void(bool&)> CallbackType;
    // typedef std::function<void(bool)> WrongCallbackType;
    using CallbackType = void(*)(bool&);
    using WrongCallbackType = void(*)(bool);
    CallbackType cb1 = [](bool b) { b = !b; }; // error 

    CallbackType cb2 = toggleOk; // Ok

    CallbackType cb3 = toggleBroken; // error 
    CallbackType cb4 = toggleInt; // error

    WrongCallbackType cb5 = toggleBroken; // Ok
    CallbackType cb6 = cb5; // error

    return 0;
}
现在在上面CallbackTypeWrongCallbackType是不同的类型,并且会按照您的预期产生错误。
但是,只能在 lambda 的情况下使用函数指针类型(如上所示),仅当 it is stateless (do not capture anything) .

关于c++ - 为什么 std::function 没有进行类型检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68971068/

相关文章:

c - const char* 应该在 C 中释放吗?

javascript - 未捕获的 ReferenceError : function is not defined at HTMLInputElement. onclick

c++ - 什么决定临时对象的生命周期何时扩展到 const 引用或右值引用?

c++ - 用来自另一个容器的迭代器填充一个容器

.net - 通过托管 C++ 使用 MMX

C++ 入门 5 版 : count reference and underlying pointers

c++ - 在成员引用中存储 move 的对象是否安全?

带有 .begin() 和 .end() 的 C++ const char

c - C中静态函数声明的区别

c++ - 关于函数引用和线程的问题