In one of my classes, I am trying to use std::priority queue
with a specified lambda for comparison:
#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;
};
My program compiles perfectly until I add a .cpp
file to accompany the header:
#include "foo.h"
int foo::bar()
{
return 0;
}
This time, my compiler generates an error:
>main.obj : error LNK2005: "class <lambda> compare" (?compare@@3V<lambda>@@A) already defined in foo.obj
Why can't I create a accompanying .cpp
file if my header file contains a lambda?
Compiler: Visual Studio 2012
My main.cpp
:
#include "foo.h"
int main(){
return 0;
}
As @Rapptz suggested,
const auto compare = [] (const int &a, const int &b) { return a > b; };
Solved the problem. Why?
Internal vs External linkage. By default, auto
, like int
has external linkage. So just how:
int j = 5;
In foo.h
that would later be included by foo.cpp
throws a
Error 2 error LNK2005: "int j" (?j@@3HA) already defined in Header.obj
(VS 2013)
However, const
makes the linkage internal by default, which means it is only accessible in one translation unit, thereby avoiding the problem.
I'm unable to replicate this problem for some reason. I'm trying this on VS2010 though - not sure if that made a difference. In fact, I tried including your header in two source files and it compiles, links and runs fine.
That said, do you want to consider using std::function
. That way you can define the lambda in the cpp code and it won't get defined multiple times for whatever reason. (BTW, where's foo.obj
coming from? Do you have another source file that is including this header ?).
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;
};
Then later in the cpp include and define the lambda and when you create the pq
pass it to the constructor.
foo.cpp:
auto compare = [] (const int &a, const int &b) { return a > b; };
foo::foo():pq(compare){}
This way you're deftly not defining the function multiple times.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With