忘れる前にメモ.
設定
- 関数の返り値として複数の値を返したい.
- 例えば,何かの処理を行い,これに成功したら返って来た値を使用して処理,失敗したら何もしない,ということができるような簡単なコードを書きたい.
- 返り値を受ける代わりにポインタを渡すのは関数インターフェースの見栄えがよろしくない.
- 適当にエンコーディングを考えて,一つの返り値に複数の値の意味を埋め込んでしまうのは,もっとよろしくない.
- 値が有効か,無効かを示すだけならBoost.Optionalがあるけど,標準ライブラリだけでどうにかしたい.
- std::optionalが標準に入るのはまだ先のようだ…
- C++11の範囲だけでどうにかする.
サンプルコード
とりあえず,サンプルを書きましたが,この例だとイテレータ使え,と言われそうですね.とりあえずパっと思い付いたものがこれなので,もっと良いサンプルがあればそれに書き直します.
返り値をstd::tupleにする場合のポイントとして,std::tieで返り値を受ける変数を指定する場合はconst宣言できない.
constな変数に返り値を代入したい場合は,普通にconst std::tuple<...>型の変数で受けて,std::getで値を参照することになる.ちょっと打つのが面倒かも.
有効か無効かを表わしたい場合,std::optionalが使えるようになったら,それを使った方が良さそう.あるいはおとなしくBoost.Optionalを使う.
#include <tuple>
#include <iostream>
#include <vector>
namespace before {
long find(const std::vector<int>& vec, const int a)
{
for(size_t i = 0; i < vec.size(); i++) {
if (vec[i] == a) {
return i;
}
}
return -1;
}
void demo()
{
const std::vector<int> vec = {0, -1, 1, 2, -2, 3};
const int a = 2;
const long b = find(vec, a);
if (b < 0) {
std::cout << a << " is not contained in vec." << std::endl;
} else {
std::cout << a << " is contained at " << b << " in vec." << std::endl;
}
const int c = -5;
const long d = find(vec, c);
if (d < 0) {
std::cout << c << " is not contained in vec." << std::endl;
} else {
std::cout << c << " is contained at " << d << " in vec." << std::endl;
}
}
}
namespace after {
std::tuple<size_t, bool> find(const std::vector<int>& vec, const int a)
{
for(size_t i = 0; i < vec.size(); i++) {
if (vec[i] == a) {
return std::forward_as_tuple(i, true);
}
}
return std::forward_as_tuple(0, false);
}
void demo()
{
const std::vector<int> vec = {0, -1, 1, 2, -2, 3};
const int a = 2;
size_t b;
bool c;
std::tie(b, c) = find(vec, a);
if (c) {
std::cout << a << " is contained at " << b << " in vec." << std::endl;
} else {
std::cout << a << " is not contained in vec." << std::endl;
}
const int d = -5;
size_t e;
bool f;
std::tie(e, f) = find(vec, d);
if (f) {
std::cout << d << " is contained at " << e << " in vec." << std::endl;
} else {
std::cout << d << " is not contained in vec." << std::endl;
}
}
template<class T, class V, class Option>
void puts_result(const T& value, const std::tuple<V, Option>& result) {
if (std::get<1>(result)) {
std::cout << value << " is contained at " << std::get<0>(result) << "." << std::endl;
} else {
std::cout << value << " is not contained." << std::endl;
}
}
void demo2()
{
const std::vector<int> vec = {0, -1, 1, 2, -2, 3};
const int a = 2;
const std::tuple<size_t, bool> b = find(vec, a);
puts_result(a, b);
const int c = -5;
const std::tuple<size_t, bool> d = find(vec, c);
puts_result(c, d);
}
}
int main()
{
before::demo();
after::demo();
after::demo2();
}