【问题标题】:Lambda in header file error头文件中的 Lambda 错误
【发布时间】:2013-08-07 20:26:35
【问题描述】:

在我的一门课程中,我尝试使用 std::priority queue 和指定的 lambda 进行比较:

#pragma once
#include <queue>
#include <vector>

auto compare = [] (const int &a, const int &b) { return a > b; };
class foo
{
public:
    foo() {  };
    ~foo() {  };
    int bar();
private:
    std::priority_queue< int, std::vector<int>, decltype(compare)> pq;
};

我的程序编译完美,直到我添加一个 .cpp 文件来伴随标题:

#include "foo.h"

int foo::bar()
{
    return 0;
}

这一次,我的编译器产生了错误:

>main.obj : error LNK2005: "class <lambda> compare" (?compare@@3V<lambda>@@A) already defined in foo.obj

如果我的头文件包含 lambda,为什么我不能创建随附的 .cpp 文件?

编译器:Visual Studio 2012

我的main.cpp

#include "foo.h"

int main(){
    return 0;
}

【问题讨论】:

  • 标记它const,这样它默认有内部链接。或者更好的是,让它成为一个仿函数。
  • 您要声明两个全局变量,均名为 compare,因为 foo.h 包含在两个单独的源文件中。我同意拉普茨。
  • 不要以这种方式使用 lambda。它们旨在创建小的局部函数,而不是通常使用的函数。这比普通函数的可读性差。
  • 我只使用 lambda 来初始化 priority_queue,但我是否应该将其切换为仿函数?顺便说一句,谢谢拉普茨
  • 我假设你只是举个例子,你的 lambda 更复杂。因为现在它相当于std::greater&lt;int&gt;

标签: c++ lambda


【解决方案1】:

正如@Rapptz 建议的那样,

const auto compare = [] (const int &a, const int &b) { return a > b; };

解决了这个问题。为什么?

Internal vs External linkage。默认情况下,autoint 一样具有外部链接。那么如何:

int j = 5;

foo.h 中,稍后将包含在foo.cpp 中会抛出一个

错误 2 错误 LNK2005: "int j" (?j@@3HA) 已在 Header.obj 中定义

(对比 2013 年)

但是,const 默认将链接设为internal,这意味着它只能在一个翻译单元中访问,从而避免了该问题。

【讨论】:

  • 已经花了一段时间试图解决这个问题 - 在 2 秒内解决它!
【解决方案2】:

由于某种原因,我无法重现此问题。不过,我正在 VS2010 上尝试这个 - 不确定这是否有所作为。事实上,我尝试将您的标头包含在两个源文件中,它可以编译、链接并运行良好。

也就是说,您是否要考虑使用std::function。这样您就可以在 cpp 代码中定义 lambda,并且无论出于何种原因,它都不会被多次定义。 (顺便说一句,foo.obj 是从哪里来的?你有另一个包含这个头文件的源文件吗?)。

foo.h:

#pragma once
#include <queue>
#include <vector>
#include <functional>

typedef std::function<bool (int, int) > comptype;
//auto compare = [] (const int &a, const int &b) { return a > b; };
class foo
{
public:
    foo() {  };
    ~foo() {  };
    int bar();

private:
    std::priority_queue< int, std::vector<int>, comptype> pq;
};

然后稍后在 cpp 中包含并定义 lambda,并在创建 pq 时将其传递给构造函数。

foo.cpp:

auto compare = [] (const int &a, const int &b) { return a > b; };

foo::foo():pq(compare){}

这样你就不用多次定义函数了。

【讨论】:

  • 是链接器错误,所以foo.obj只是编译后的文件
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多