2013-08-07 4 views
6

In einer meiner Klassen, ich versuche std::priority queue mit einem angegebenen Lambda zum Vergleich zu verwenden:Lambda in Header-Datei Fehler

#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; 
}; 

Mein Programm kompiliert perfekt, bis ich eine .cpp Datei hinzufügen, um den Header zu begleiten:

#include "foo.h" 

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

Dieses Mal erzeugt mein Compiler einen Fehler:

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

Warum kann ich keine begleitende Datei .cpp erstellen, wenn meine Header-Datei ein Lambda enthält?

Compiler: Visual Studio 2012

Mein main.cpp:

#include "foo.h" 

int main(){ 
    return 0; 
} 
+5

Mark es 'const', so dass es interne Verknüpfung standardmäßig hat. Oder noch besser, mach es zu einem Funktor. – Rapptz

+3

Sie deklarieren zwei Globals, die beide 'compare' heißen, weil' foo.h' in zwei separaten Quelldateien enthalten ist. Ich stimme Rapptz zu. – WhozCraig

+1

Verwenden Sie keine Lambdas auf diese Weise. Sie sollen kleine lokale Funktionen erzeugen, nicht allgemein benutzte Funktionen. Dies ist weniger lesbar als eine normale Funktion. – GManNickG

Antwort

5

Als @Rapptz schlug

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

das Problem gelöst. Warum?

Internal vs External linkage. Standardmäßig hat auto, wie int externe Verknüpfung. So einfach, wie:

int j = 5; 

In foo.h, die später von foo.cpp aufgenommen werden würde wirft ein

Error 2 error LNK2005: "int j" ([email protected]@3HA) already defined in Header.obj

(VS 2013)

Allerdings macht const die Verknüpfung interne standardmäßig die bedeutet, dass es nur in einer Übersetzungseinheit zugänglich ist, wodurch das Problem vermieden wird.

+0

Habe eine Weile versucht, dies zu bekommen - löste es in 2 Sekunden flach! – davidhood2

0

Ich bin nicht in der Lage, dieses Problem aus irgendeinem Grund zu replizieren. Ich versuche dies auf VS2010 - nicht sicher, ob das einen Unterschied machte. In der Tat habe ich versucht, Ihren Header in zwei Quelldateien zu integrieren und kompiliert, verknüpft und läuft gut.

Das gesagt, möchten Sie in Betracht ziehen, std::function zu verwenden. Auf diese Weise können Sie das Lambda im cpp-Code definieren und es wird aus irgendeinem Grund nicht mehrfach definiert. (BTW, wo kommt foo.obj her? Haben Sie eine andere Quelldatei, die diesen Header enthält?).

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; 
}; 

Dann später in der CPP enthalten und das Lambda definieren und beim Erstellen des pq Passes es an den Konstruktor.

foo.cpp:

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

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

Auf diese Weise sind Sie geschickt die Funktion mehrmals nicht definieren.

+0

Es ist ein Linker-Fehler, so 'foo.obj' ist nur die Datei nach der Kompilierung – yizzlez

Verwandte Themen