【问题标题】:Why does this functor ("lambda") give a weird warning?为什么这个函子(“lambda”)会给出一个奇怪的警告?
【发布时间】:2011-08-25 05:20:47
【问题描述】:

当我使用 Visual C++ 2010 编译和运行它时:

#include <iostream>

int main() {
    int subtrahend = 5;

    struct Subtractor {
        int &subtrahend;
        int operator()(int minuend) { return minuend - subtrahend; }
    } subtractor5 = { subtrahend };

    std::cout << subtractor5(47);
}

我得到正确答案,42。

然而,编译器抱怨这是不可能的:

Temp.cpp(9):警告 C4510:main::Subtractor无法生成默认构造函数
Temp.cpp(6) : 参见声明 main::Subtractor

Temp.cpp(9):警告 C4512:main::Subtractor无法生成赋值运算符
Temp.cpp(6) : 参见声明 main::Subtractor

Temp.cpp(9) : 警告 C4610: struct main::Subtractor 永远无法实例化 - 需要用户定义的构造函数

发生了什么事?

【问题讨论】:

  • 您如何获得42 作为答案? 48-5 等于 42 吗?
  • @Nawaz:大声笑,很好的收获。这是因为我最初是用 48 进行测试,但后来我认为 47 会是一个更有趣的例子,所以我放下了 42。在复制/粘贴错误期间,47 又爬了回来。 :P
  • 为什么你认为47 会是“更多”有趣的例子?它有什么特别之处?你的年龄是? :P
  • 这段代码中没有 lambda。
  • @Nawaz:哈哈,不,我离 42 还差得很远。:PI 只是认为 42 的最终结果可能会更好,所以我将 48 更改为 47。(不过现在很遗憾,哈哈)

标签: c++ templates visual-c++ anonymous-types functor


【解决方案1】:

前两个警告只是让您知道由于引用数据成员的存在而无法生成隐式声明的成员函数。

第三个警告是a Visual C++ compiler bug

可以忽略所有三个警告而不会产生不良影响,尽管您可以通过将引用数据成员改为指针来轻松消除所有三个警告(引用数据成员几乎不值得麻烦)。

【讨论】:

  • +1 似乎是正确的答案——将int &amp; 更改为int 也会使第三个警告消失!没想到是个bug;有趣,谢谢...
【解决方案2】:

第一个警告是告诉你不能默认构造引用值(引用保证指向某个值)。将减数转换为常规整数,问题就会消失。

我很确定第二个警告具有相似的性质。

(只是说,通常依赖于 boost::function 或类似的实现(std::tr1::function?)而不是手动编写此代码要好得多)

【讨论】:

  • 我实际上使用的是较旧的编译器(所以没有 TR1),我只是用 VC 2010 对其进行了测试,以确保它不是编译器问题(部分是!)。而且我试图远离 Boost,因为这应该是轻量级的东西,但无论如何 +1 的想法。
  • @Ethan:第二个警告确实具有相似的性质。引用不能被重新定位,因此您不能分配给它(它会分配给被推荐人)。
【解决方案3】:

这是因为变量减法器5 是一个未命名的结构。如果您想让错误消失,请给用于减法器 5 的结构命名。

例如:

struct subtractor {
 :
} subtractor5 = { subtrahend };

不幸的是,我对 C++ 语言的了解不够多,无法知道它为什么起作用,但我知道为什么会出现警告。

【讨论】:

  • 我不确定我是否理解正确,但我尝试用struct Subtractor { 替换struct { 并没有改变任何东西。 (刚刚也更新了我的问题。)
  • 有趣。我关注的是“未命名”方面,而不是错误的其余部分。
  • 这里完全一样——我之前肯定见过这个错误,关于默认的构造函数/引用变量。由于未命名的问题(以及第三个错误),我完全错过了这种可能性。
【解决方案4】:

在以下情况下,用户定义的构造函数是必需的:

  • 正在初始化常量数据成员 (const int c_member;)。
  • 初始化引用数据成员 (int &amp; r_member;)
  • 拥有一个类型没有默认构造函数的数据成员。例如:

    类 NoDefCtor { 民众: NoDefCtor(int); };

    类包含那 { NoDefCtor no_ctor_member; };

  • 从基类继承,其中基类没有默认构造函数。几乎和上面一样(NoDefCtor)。

【讨论】:

  • 不要忘记没有默认构造函数的基类的虚拟继承。
猜你喜欢
  • 2023-02-05
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
相关资源
最近更新 更多