在我的一个课程中,我试图将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;
}
答案 0 :(得分:7)
正如@Rapptz建议的那样,
const auto compare = [] (const int &a, const int &b) { return a > b; };
解决了这个问题。为什么呢?
Internal vs External linkage。默认情况下,auto
与int
一样具有外部链接。那么如何:
int j = 5;
foo.h
稍后会被foo.cpp
包含在内的const
会抛出
错误2错误LNK2005:&#34; int j&#34; (?j @@ 3HA)已在Header.obj中定义
(VS 2013)
但是,{{1}}默认情况下会建立链接内部,这意味着它只能在一个翻译单元中访问,从而避免了这个问题。
答案 1 :(得分:0)
由于某种原因,我无法复制此问题。我在VS2010上尝试这个 - 不确定这是否有所作为。事实上,我尝试将您的标题包含在两个源文件中,它编译,链接和运行正常。
那就是说,你想考虑使用std::function
吗?这样你就可以在cpp代码中定义lambda,并且不会出于任何原因多次定义它。 (BTW,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){}
这样你就不会多次定义这个函数了。