A、タプルの概要
- タプルと同様のペア、だけでなく、テンプレート。ペアは、二つの部材、かかるメンバーの任意の数を受け入れるようにタプルを
- 我々は1つのオブジェクトにいくつかのデータを組み合わせたい場合は、タプル便利
- 以下に、サポート業務は、タプルであるヘッダファイルタプル内に定義されています。
第二に、定義と初期化タプル
- 我々はタプルを定義する場合、それは各メンバーの種類を注意する必要があります。
std::tuple<size_t, size_t, size_t> threeD; //使用默认构造函数
std::tuple<std::string, std::vector<double>, int, std::list<int>>
someVal("constants", { 3.14,2.718 }, 42, { 0,1,2,3,4,5 });
- タプルのコンストラクタは、明示的であり、したがって、直接初期化構文を使用する必要があります。
std::tuple<size_t, size_t, size_t> threeD1 = { 1,2,3 }; //错误
std::tuple<size_t, size_t, size_t> threeD2{ 1,2,3 }; //正确
- あなたもできるmake_pair()関数を使用するタプルオブジェクトを生成します:
auto item = std::make_tuple("0-999-78345-X", 3, 20.00);
//item类型为tuple<const char*, int, double>
第三に、アクセスタプルメンバー
取得()関数
- 私たちは、最初の要素と容器の第2の要素にアクセスするための第一及び第二の対を使用することができます。我々はので、しかし、タプルコンテナのメンバーの数は、限定されるものではなく、タプルのアクセス要素を取得するには、標準ライブラリ関数テンプレートを使用する必要があります。
- getを使用するためには、我々は明示的なテンプレート引数を指定する必要がありますいくつかのメンバーの最初へのアクセスを示すために、インデックスのメンバーは0から始まります
- 取得返しに指定したメンバーの参照を
- 例えば:
auto item = std::make_tuple("0-999-78345-X", 3, 20.00); auto book = std::get<0>(item); //返回item第一个成员 auto cnt = std::get<1>(item); //返回item第二个成员 auto price = std::get<2>(item) / cnt; //返回最后一个成员,并将其除以cnt std::get<2>(item) *= 0.8; //打折20%(get返回的是item的引用)
tuple_sizeクラステンプレート、tuple_elementクラステンプレート
- tuple_size:それはメンバーの数で与えられたタプルを表す、パブリック静的データのメンバ名前の値を有します
- tuple_element:それは次に公衆のメンバーによって与えられた組の指定されたメンバーのメンバーを表すデータのタイプと呼ばれる、インデックスとタプルタイプを取り
//item的类型为tuple<const char*, int, double> auto item = std::make_tuple("0-999-78345-X", 3, 20.00); //trans为item的数据类型 typedef decltype(item) trans; //返回item中的数据成员数量 size_t sz = std::tuple_size<trans>::value; //type为int std::tuple_element<1, trans>::type cnt = get<1>(item);
四、リレーショナルと平等演算子
- 以下は、通常のSTLコンテナの比較であります:
- 同じサイズの2つのコンテナとすべての要素が2つの2等しいに対応する場合、2つの容器が等しい、等しくない、さもなければ
- 両者は同じ大きさの容器ではなく、より小さなコンテナの各要素は、より大きな容器よりも大きい、容器、以下の小さい血管における対応する要素と等しい場合
- 二つの容器が他の容器の接頭辞のシーケンスでない場合は、比較結果の比較結果に依存等しくない要素がありません
- タプルは比較規則のSTLコンテナに似ていますが、:
- メンバの同じ番号を持つ2つの組を比較することができる場合にのみ
- 等しいまたは等しくない演算子を使用するために、等しい又は等しくないオペレータの各対のメンバーは、合法的でなければなりません
- 関係演算子の使用と同様に、各部材を使用する関係演算子には、法的でなければなりません
- 例えば:
std::tuple<std::string, std::string> duo("1", "2");
std::tuple<size_t, size_t> twoD(1, 2);
bool b = (duo == twoD); //错误,string与size_t类型不一致无法比较
std::tuple<size_t, size_t, size_t> threeD(1, 2, 3);
b = (twoD < threeD); //错误,tuple的成员数量不同
std::tuple<size_t, size_t> origin(0, 0);
b = (origin > twoD); //正确,b为true
第五に、戻り値のタプルの複数の使用
- タプル関数からの戻り値の複数の一般的な使用を。ここでは、ステップのデモンストレーションケースバイステップをご紹介します
- SALES_DATAは、カスタムクラス、ある書籍の価格、販売記録の数が含まれています
#include <iostream>
#include <ostream>
#include <sstream>
#include <fstream>
#include <string>
#include <iterator>
#include <vector>
#include <tuple>
#include <algorithm>
#include <numeric>
using namespace std;
struct Sales_data {
std::string isbn()const { return bookNo; }
Sales_data(const string& s) :bookNo(s), units_sold(0), revenue(0) {}
Sales_data &operator+=(const Sales_data &rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
ostream &operator<<(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue << ;
return os;
}
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) {
Sales_data sum = lhs;
sum += rhs;
return sum;
}
- 今、私たちは、変数ファイルを定義するすべての書店店頭販売に使用し、:
/*
vector<Sales_data>代表一家书店的销售情况
vector<vector>代表所有书店
*/
vector<vector<Sales_data>> files;
- タプルを返す関数を書きます:
- レッツ・書き込み、その与えられた書籍について、この本の書店を通じて販売するファイルの検索関数
- 各レコードの売上高については、書店保存、タプル型を返し、2回の反復子のインデックス(ファイル内のインデックス位置は本屋で示され、書籍ベクトルイテレータが本屋<SALES_DATA>最初に、本明細書に示されています記事の販売記録と販売最後のレコードの後の位置)
- equal_rangeアルゴリズム:
- 指定された範囲イテレータ内の要素で指定された3つのパラメータを探し
- 我々はcompareIsbn呼び出される関数へのポインタを渡すようにデフォルトのアルゴリズム<比較するための演算子、何SALES_DATA <演算子がないので、
- アルゴリズムは、ペアを返す要素の範囲を表します。見つからない場合、反復子が等しく、それは空の範囲を表します。
//equal_range算法比较函数
bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs)
{
return lhs.isbn() < rhs.isbn();
}
vector<vector<Sales_data>> files;
//声明一个别名
typedef tuple<vector<Sales_data>::size_type,
vector<Sales_data>::const_iterator,
vector<Sales_data>::const_iterator> matches;
//返回一个类型为tuple的vector
vector<matches> findBook(const vector<vector<Sales_data>> &files, const string &book)
{
vector<matches> ret;
//遍历files
for (auto it = files.cbegin(); it != files.cend(); ++it)
{
//在it所在的书店中寻找名为book的书籍,返回值见上面介绍
auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);
//如果找到了,添加到ret中
if (found.first != found.second)
ret.push_back(std::make_tuple(it - files.cbegin(), found.first, found.second));
}
return ret;
}
- 関数が返すタプルを使用します。
- ループは、中のSと呼ばれる本から読み取った後、Sという本があるかどうかを見つけるためにfindBook機能の上に呼び出している間
- ない場合は、findBookはベクトルが空で返され、その後、サイクルは継続使用を継続
- あなたは、各要素がタプルであるトランス、ベクトルループを反復処理のために使用することを発見した場合は
- そして、3つの要素でタプルをゲット0,1,2と印刷
- 前記アルゴリズム累算(我々はSALES_DATA加算演算子を定義するので、このアルゴリズムを使用することができます)。図3は、パラメータが構築にSALES_DATA列コンストラクタである初期値にパラメータを蓄積します。我々はSALES_DATA <<演算子を定義するためにも、それはostreamに出力することができます
void reportResults(istream &in, ostream &os, const vector<vector<Sales_data>> &files)
{
std::string s; //要查找的书籍
while (in >> s)
{
auto trans = findBook(files, s);
if (trans.empty()) {
std::cout << s << "not found in any stores" << std::endl;
continue;
}
else {
for (const auto &store : trans) {
os << "store: " << std::get<0>(store) << std::endl;
os << "sales: " << std::accumulate(std::get<1>(store), std::get<2>(store), Sales_data(s)) << std::endl;
}
}
}
}