【问题标题】:No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called没有可以执行此转换的用户定义转换运算符,或者无法调用该运算符
【发布时间】:2016-11-11 02:52:13
【问题描述】:

我有一个奇怪的错误,我不太明白,VS2013。 这只是我的实际问题的简化,导致相同的错误。

std::function<bool()> x = (someCondition == true)
    ? []() { return true; }
    : []() { return false; };

VS 编译器错误是:

1>f:\test\cppconsoleapplication\cppconsoleapplication.cpp(497): error C2446: ':' : no conversion from 'main::<lambda_96d01fe3721e46e4e8217a69a07d151b>' to 'main::<lambda_0d38919a9b2aba5caf910d83eac11776>'
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

IntelliSense 甚至提出了这个神秘的错误信息:

IntelliSense: more than one operator "?" matches these operands:
        built-in operator "expression ? pointer : pointer"
        built-in operator "expression ? pointer : pointer"
        built-in operator "expression ? pointer : pointer"
        built-in operator "expression ? pointer : pointer"
        operand types are: lambda []bool ()->bool : lambda []bool ()->bool  f:\Test\CppConsoleApplication\CppConsoleApplication.cpp 496

而以下编译

std::function<bool()> x = []() { return true; };

if (someCondition == false)
    x = []() { return false; };

这只是 VisualStudio 的错误之一还是我在这里做错了什么?

【问题讨论】:

  • VS2013 不完全支持 C++11 功能。试试VS2015。您也可以尝试将一个 lambda 显式转换为函数指针以强制推断常见类型。

标签: c++ lambda conditional-operator std-function


【解决方案1】:

您的代码很好,MSVC 拒绝它是错误的。根据documentation

条件表达式 E1 的类型和值类别? E2 : E3 根据以下规则确定:
[1-4 不适用]
5) 否则,结果为纯右值。 如果 E2 和 E3 没有相同的类型,并且任何一个都具有(可能是 cv 限定的)类类型,则使用下面的内置候选执行重载决议,以尝试将操作数转换为内置类型。 如果重载解析失败,则程序格式错误。否则,将应用选定的转换,并使用转换后的操作数代替步骤 6 的原始操作数。

上述内置候选包括一个试图将两个操作数都转换为指针的候选。由于两个 lambdas 都有一个空的捕获列表,它们可以转换为bool(*)(),所以应该选择这个候选者。 (其他的候选项不适合,所以指针一没有歧义。)

总结一下:

(someCondition == true)
    ? []() { return true; }
    : []() { return false; };

应将两个 lambda 转换为 bool(*)() 并生成一个指向函数的指针,该函数在调用时与所选 lambda 具有相同的效果。这个指针不是悬空的,独立于 lambda 对象的生命周期。 (详情here.)
然后可以将生成的函数指针分配给std::function

请注意,两个具有空捕获列表的 lambdas 是至关重要的。如果其中一个 lambdas 捕获了某些东西,那么到指针的转换将不再起作用,并且代码将是错误的。

您可以通过将一个或两个 lambda 显式转换为 bool(*)()std::function&lt;bool()&gt; 来帮助您的旧 MSVC。后者还允许您将 lambdas 与非空捕获列表一起使用。 (Live)


解释 IDE 为您提供的诊断:

编译器错误似乎源于我链接的列表中的步骤 3):它尝试将一个操作数转换为另一个操作数的类型并失败。

IntelliSense 似乎至少有正确的想法,并抱怨第 5 步中描述的重载解决方案)。为什么它找到了太多我不知道的候选人。这是一个错误。

【讨论】:

    猜你喜欢
    • 2012-10-26
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 2021-04-05
    • 2020-08-10
    • 1970-01-01
    • 2010-11-21
    相关资源
    最近更新 更多