2016-02-04 17 views
12

std::priority_queueのコンストラクタが定数参照によってコンパレータを受け入れる理由はありますか?コンパレータが範囲外になるとどうなりますか?std :: priority_queueのコンパレータ

@LightnessRacesInOrbitが指摘したように、私はおそらく、コンパレータを動かすのコンテキストでこのことについて考えていました!

これについての投稿が既にある場合は申し訳ありません。私はそれを見つけることができていない!

+1

優秀な質問です。私はこれについて決して考えなかった。 –

+3

ラムダに関するあなたの声明はあまり意味がありません。ラムダをコピーすることができます... –

答えて

8

私は以前これについて考えたことはありませんでしたが、const-refは実際には少し誤解を招いています。しかし、機能のシグネチャは、移動セマンティクスが来る前に考えられ、すべてを価値によって受け入れることが流行となりました。確かに、コンパレータがコピーされます!

[C++14: 23.6.4.1/4]:効果:yxcと初期化comp(コピーが構築又は適宜構築移動)。 c.insert(c.end(), first, last);を呼び出し、最後にmake_heap(c.begin(), c.end(), comp).

ラムダはコピーアサインされていない呼び出しますが、彼らはコピー構築可能ですので、何の問題がここにはありません。

[C++14: 5.1.2/20]:ラムダ式に関連付けられている閉鎖型削除(8.4.3)デフォルトのコンストラクタ、削除、コピー代入演算子を有しています。暗黙的に宣言されたコピーコンストラクタ(12.8)を持ち、暗黙的に宣言された移動コンストラクタ(12.8)を持つことができます。 [..]

これはコンパレータ自体の移動を妨げますか?はい、そうです。私はこのコンベンションで、コンパレータをconst-refでコピーしてコピーすると、移動セマンティクスの前にSTLの日に由来すると仮定します。私は、複雑さを増し、複雑で動きのあるエンハンシブルなコンパレータを最初に置いてはいけないので、コンパイラを価値あるものにするためにオーバーロードを追加することは真剣に考慮されていなかったと思います()。それでも、このは、コンパレータを動かすための実用的な使用例を考え出すことができれば、委員会と一緒に持ち上げる価値があります。

+0

コンパイラを動かす移動コンストラクタがない理由について私に考えさせてください! – Curious

+1

@Curious:コンパレータに移動コンストラクタがある場合は、呼び出されます。 –

+0

うーん..私はちょうどチェックした。それは本当です。右辺のコンストラクタが提供されているかどうかがより明確になるような気がします! – Curious

4

std::priority_queueのコンストラクタは、コンパレータのコピーを作成し、それがスコープの外に出るかどうかは問題ではありません。

あなたは直接の比較タイプとしてstd::function<bool(const T&, const T&)>を使用して、またはのいずれかによってコンパレータとしてラムダを使用することができます。

auto comp = [](int x, int y) { return x > y; }; 
std::priority_queue<int, std::vector<int>, decltype(comp)> q(comp); 

あなたはヘルパー関数でこれを容易にすることができる。

template<typename T, typename Compare> 
auto make_priority_queue(Compare&& comp) { 
    return std::priority_queue<T, std::vector<T>, Compare>(std::forward<Compare>(comp)); 
} 

int main() { 
    auto q = make_priority_queue<int>([](int x, int y) { return x > y; }); 
} 
+0

しかし、どのようにラムダを使用することができますか? – Curious

+2

@Curious:それらもコピーできます。 –

+0

@LightnessRacesinOrbit私は、彼らはコピーすることができないし、デフォルトのコピーコンストラクタが削除されているという印象を受けましたか?あなたはこれを成功させることができる例を教えてください。 – Curious

5

それは行っておりません。範囲外です。コピーがコンテナに組み込まれています。 cppreference.com状態に関する説明は:

explicit priority_queue(const Compare& compare = Compare(), 
         const Container& cont = Container()); 

続きの内容と基本的なコンテナCをコピーし、構築します。コピー - 比較ファンクタのcompをcompareの内容で構成します。 std :: make_heap(c.begin()、c.end()、comp)を呼び出します。これもデフォルトのコンストラクタです。

コンストラクタにはさまざまな形式がありますが、いずれの場合も、内部コンパレータは供給されたものからコピーまたは移動構成されています。

+0

しかし、lambdasは正しく構築されたコピーができませんか? – Curious

+1

@Curious:どこでそれを読んだのですか? –

+0

私はその問題を自分で解決しました... – Curious

関連する問題