404 Not Found

404 Not Found


nginx

コンテナアダプタ

[第]38[課では]functionobjectについて学びました。

[今]、[私たちは]関数[アダプター]について学びます――[既存の]関数を[「改造」]して[必要な形に]するものです。

[まるでレゴブロックのように]、[小さなパーツを組み合わせて大きな作品を作り上げる]。


1. [アダプターの概要]

(1) 1.1 [アダプター]とは何か?

[アダプター](Adapter)は、[修正]functionobject[の動作]テンプレートです。

[一般的なアダプター]:



2. std::bind——[引数のバインド]

基本的な使い方

std::bind [関数のパラメータを[バインド]するために使用し、[新しい]関数オブジェクトを[作成]します。

例:[パラメータのバインド] (難易度 ⭐⭐)

▶ サンプル 2: codeexample (難易度 ⭐)

CPP
#include iostream
#include functional

int add(int a, int b) {
 return a + b;
}

int main() {
 // Bind first parameter of add to 10
 auto add10 = std::bind(add, 10, std::placeholders::_1);
 
 std::cout << "add10(5) = " << add10(5) << std::endl; // output:15
 std::cout << "add10(20) = " << add10(20) << std::endl; // output:30
 
 return 0;
}
▶ 試してみよう

💡 ヒント:


(2) 2.2 [パラメータの順序の調整]

例:[引数の順序を入れ替える] (難易度 ⭐⭐)

CPP
#include iostream
#include functional

int subtract(int a, int b) {
 return a - b;
}

int main() {
 // Swap parameter order
 auto reverse_subtract = std::bind(subtract,
 std::placeholders::_2,
 std::placeholders::_1);
 
 std::cout << "subtract(10, 3) = " << subtract(10, 3) << std::endl; // 7
 std::cout << "reverse(10, 3) = " << reverse_subtract(10, 3) << std::endl; // -7
 
 return 0;
}


3. std::ref——参照[ラップ]

(1) 3.1 [問題]:値渡し

[デフォルトでは]、STLアルゴリズムは[値渡し]の関数オブジェクトとして動作するため、[状態を共有することができません]。

例:[用]std::ref[解決] (難易度 ⭐⭐)

CPP
#include iostream
#include algorithm
#include vector
#include functional

struct Counter {
 int count = 0;
 void operator()(int) { count++; }
};

int main() {
 std::vectorint v = {1, 2, 3, 4, 5};
 Counter counter;
 
 // ❌!pass by value,counter'scalling
 std::for_each(v.begin(), v.end(), counter);
 std::cout << ":" << counter.count << std::endl; // output:0
 
 // ✅!Usingstd::refbyreference
 std::for_each(v.begin(), v.end(), std::ref(counter));
 std::cout << ":" << counter.count << std::endl; // output:5
 
 return 0;
}


4. std::not_fn——[反転]

基本的な使い方

std::not_fn [functionobjectの戻り値を反転させるために使用します]。

例:[反転述語] (難易度 ⭐⭐)

CPP
#include iostream
#include vector
#include algorithm
#include functional

int main() {
 std::vectorint v = {1, 2, 3, 4, 5};
 
 // Find first even number
 auto it1 = std::find_if(v.begin(), v.end(),
 (int x) { return x % 2 == 0; });
 std::cout << ":" << *it1 << std::endl; // 2
 
 // Find first odd number (negated)
 auto it2 = std::find_if(v.begin(), v.end(),
 std::not_fn((int x) { return x % 2 == 0; }));
 std::cout << ":" << *it2 << std::endl; // 1
 
 return 0;
}


5. std::mem_fn——メンバ関数ポインタ

(1) 5.1 [問題]:メンバー関数ポインタ[使いにくい]

メンバー関数ポインタ[構文が複雑]、std::mem_fn [を使用すれば] [簡略化できる]。

例:[呼び出し]メンバー関数 (難易度 ⭐⭐⭐)

CPP
#include iostream
#include vector
#include algorithm
#include memory

struct Student {
 std::string name;
 void display() const {
 std::cout << "Student: " << name << std::endl;
 }
};

int main() {
 std::vectorStudent students = {{"..."}, {"..."}};
 
 // std::mem_fn
 std::for_each(students.begin(), students.end(),
 std::mem_fn(&Student::display));
 
 return 0;
}


6. [総合]例

▶ サンプル 1: [柔軟な成績処理機能] (難易度 ⭐⭐⭐)

CPP
#include iostream
#include vector
#include algorithm
#include functional

int main() {
 std::vectorint scores = {85, 92, 78, 90, 88};
 int threshold = 90;
 
 // Count scores not below threshold
 int count = std::count_if(scores.begin(), scores.end(),
 std::bind(std::greater_equalint(),
 std::placeholders::_1,
 threshold));
 
 std::cout << "not below" << threshold << "people scoring:" << count << std::endl;
 
 return 0;
}
▶ 試してみよう

❓ よくある質問

Q:C++11には[まだ]std::bind[はありますか]? A:[あります]が、[ただし]ラムダ式[の方が推奨されます]。ラムダ式[の方が簡潔]で、パフォーマンスも[優れています]。

CPP
// std::bind
auto f1 = std::bind(add, 10, std::placeholders::_1);

// Lambda()
auto f2 = (int x) { return add(10, x); };

Q:[いつアダプターを使うのか]? A:[既存の]関数が[ほぼ][要件を満たしている]が、[引数が一致しない場合]。


Q:STL adaptersについて最も重要なことは何ですか? A:まず核心概念を理解し、その後実践的な例で練習することが重要です。

📖 まとめ

[アダプター] [機能]
std::bind [パラメータの紐付け]
std::ref [按]参照渡し
std::not_fn [取り消し]
std::mem_fn メンバー関数ポインタ

📝 練習問題

  1. **初心者(難易度 ⭐):[stackint を作成し]、[順番に] 1、2、3 を push し、[その後] ループで pop を行い、[すべての要素を] 出力する。[出力される] 順序を[確認する]。

  2. **中級(難易度 ⭐⭐):[用] queue [「印刷タスクのキュー」を実装する]――[複数の印刷タスクが順番に処理される様子をシミュレートし]、[1つずつ処理した後]、[キューの残りの長さ]を出力する。

  3. **上級(難易度 ⭐⭐⭐):[用] priority_queue [「タスクスケジューラ」を実装する]――[各タスクには優先度](1~10)が設定されており、[キューは優先度の高い順に処理され]、[同じ優先度のタスクは挿入順に処理される]。


  1. [アダプタ]:stack/queue/priority_queue のカプセル化[基盤]コンテナ
  1. [アダプタは]templateパラメータ[を通じて、基盤となる]コンテナを指定する

[次のレッスン]:例外処理(#40)

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%