2013-08-07 10 views
6

で、私は比較のために指定されたラムダとstd::priority queueを使用しようとしています:私は、ヘッダーに同行する.cppファイルを追加するまでラムダ私のクラスの一つのヘッダファイルエラー

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

私のプログラムは完全にコンパイルします。

#include "foo.h" 

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

この時、私のコンパイラはエラーを生成します。

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

ヘッダーファイルにラムダが含まれている場合、なぜ添付ファイル.cppを作成できないのですか?

コンパイラ:Visual Studioの2012

マイmain.cpp

#include "foo.h" 

int main(){ 
    return 0; 
} 
+5

これを 'const'とすると、デフォルトで内部リンケージがあります。それとももっと良いことに、それをファンクターにしてください。 – Rapptz

+3

'foo.h'が2つの別々のソースファイルに含まれているので、' compare 'という名前の2つのグローバルを宣言しています。私はRapptzと同意する。 – WhozCraig

+1

このようにラムダを使用しないでください。それらは、一般的に使用される関数ではなく、小さなローカル関数を作成するためのものです。これは、通常の関数よりも読みにくいです。 – GManNickG

答えて

5

@Rapptzが示唆したように、

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

は、問題を解決しました。どうして?

Internal vs External linkage。既定では、intのようにautoが外部リンケージを持っています。しかし、constはデフォルトでリンケージ内部を行い、後にfoo.cppによって含まれることになるfoo.h

int j = 5; 

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

(VS 2013)

をスローし、その:だから、どれだけ1つの翻訳単位でしかアクセスできないため、問題を回避できます。

+0

これを取得しようとしたことがありましたか?2秒で解決しました! – davidhood2

0

私はいくつかの理由でこの問題を再現することができないんです。私はVS2010でもこれを試しています。違いがあるかどうかはわかりません。実際、ヘッダーを2つのソースファイルに含めようとしましたが、コンパイル、リンク、正常に実行されます。

つまり、std::functionの使用を検討しますか?そうすれば、cppコードでラムダを定義することができ、何らかの理由で何度も定義されることはありません。 (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で含めるとラムダを定義すると、あなたは、コンストラクタにpqパスを作成するとき。

foo.cpp:

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

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

あなたが巧みに機能を複数回定義していないこの方法です。

+0

リンカのエラーですので、 'foo.obj'はコンパイル後のファイルです – yizzlez

関連する問題