【问题标题】:Odd behaviour of std::function copy operator (MSVC2012)std::function 复制运算符的奇怪行为 (MSVC2012)
【发布时间】:2015-04-16 08:10:10
【问题描述】:

我在尝试使用函数对象时遇到了 bad_function_call 异常的问题。

发现问题导致我进入下一个简单示例: http://ideone.com/Mwvw7s

主要摘录:

std::function<void(void*)> f1;
std::function<void(const void*)> f2;
f1 = f2; // Could fail, but didn't

if(f1)
    f1(nullptr); // Should never run
else 
    std::cout << "Skip f1" << std::endl; // Should run

if(f2)
    f2(nullptr);
else 
    std::cout << "Skip f2" << std::endl;

这个 f1 生效,不管 f2。 此问题仅在 MSVC2012 上出现(未尝试任何其他版本的 MS 编译器)并且在 GCC 中按预期工作。

问题是:

  1. 这个问题是 MSVC2012 特有的吗? (任何人都可以在 MSVC2013 上进行测试)
  2. 这个问题众所周知吗?
  3. [如果 1 和 2 为“否”] 我应该向谁投诉?

更新

  1. MSVC2013 不会重现此类问题。
  2. 以防万一有人关心,GitHub 存储库有问题:https://github.com/comargo/functional_test

【问题讨论】:

    标签: c++ visual-c++ std-function visual-studio-2012


    【解决方案1】:

    这似乎是 MSVC2012 的问题; MSVC2013 运行正确 (live example)。

    从模板的不同实例化(即具有不同签名)分配function 类模板实例化实例委托给构造函数,并由 [func.wrap.func 的特殊子句处理。缺点]

    8 - 后置条件: !*this 如果以下任何一项成立:[...]

    • Ffunction 类模板的实例,!f

    我猜想库实现者未能为 MSVC2012 实现此子句;在function 类模板实例之间进行转换时,最直接的策略是将源类型包装在转换包装器中;很容易忘记检查源实例是否已启用。

    作为一种解决方法,您可以编写:

    f2 ? (f1 = f2) : (f1 = nullptr);
    

    【讨论】:

    • 我的策略是“不要忘记常量修饰符”。有效函数对象的复制转换工作正常。唯一的失败是无效(nullptr)函数对象的副本。不幸的是,很难追踪问题的根源,因为它的功能由定义声明。
    • 不幸的是,这是一个复制构造函数调用,我将 'f2' 类型传递给预期的 'f1' 类型的函数,因此解决方法不合适。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    相关资源
    最近更新 更多