2017/10/02

[c++]boost::tie ?

前にboostを使って最短経路を求める(1,2,3,4,5)というのをやった。
そのときは目的を達成できてよかったのだが、今になってよくわかっていないところがあることに気付いた。

サンプルソースのここで並び替えを行っているのだが、本業ではこの箇所で辺(edge)に載っているデータを使って計算するようにしていた。

bool found;
graph_t::edge_descriptor e; boost::tie(e, found) = edge(v, p[v], g);

これで、foundがtrueになれば、該当するedgeの番号がeに入ったことになるらしい。

しかし、別の箇所では

boost::tie(e1, inserted) = boost::add_edge(v1, v2, graph);

などとしている。

単に戻り値をeやe1に入れるだけなら、boost::tieなどいらないはずだ。
そもそも、boost::tieってなんだ??


http://www.boost.org/doc/libs/1_65_1/libs/tuple/doc/tuple_users_guide.html

tupleは要素数固定のデータ集、でよいのかな?
そして、tieはtupleだけど要素が固定値ではないもの・・・?


std::pairは2つ限定だし、std::tupleはC++11からのようだから、boostにあったtupleがC++11に入ったのかな?
よく見ると、std::tieもC++11にあるそうだ。
boostのtieとstdのtieは同じものだろうか?

いろいろ疑問はあるが、今回はboost::tieの使い方を知りたいだけだ。
消極的だが、やむを得ん。


int i; char c; double d; 
tie(i, c, d) = make_tuple(1,'a', 5.5);

左辺にtieを置いても、ちゃんと使えるようだ。

ということは、最初に挙げた例のfoundやinsertedも、単に変数として使っているだけか。

いや、この引数がboost::tie::inserted、みたいな役割を持っていて、それによって何か結果が変わってくるんじゃないかと心配していたのだ。
自分でbool変数を作っているのだし、それはないか。


これで終わらせようとしたが、さすがにサンプルコードくらいは書かねばなるまい。

/*
 * $ g++ -o tst tietie.cpp
 */
#include <iostream>
#include "boost/tuple/tuple.hpp"

int main(void)
{
    int a;
    std::string b;
    boost::tie(a, b) = boost::make_tuple(123, "yoshio");
    std::cout << a << ", " << b << std::endl;
    return 0;
}

123, yoshio


まあ、そのまんまですな。。。

なんというか、局所的な構造体っぽい使い方ができるのかな?
ただ、戻り値を構造体にするとなると、構造体を定義して、実装側と使う人がincludeなどで共通の構造体を使わないといかんけど、tieだと型と順番が揃っていればよい。

けど、だったら構造体でもいいんじゃないの、という気がするが、構造体が増えていくのも面倒な気がする。
型は同じだけど用途が異なるので、中身が同じ構造体を別に用意する、みたいなことはしなくてよいか。


なんとなく、gcc -Sでアセンブラ展開すると、700行近くなった。
試しに、2行追加してみる。

/*
 * $ g++ -o tst tietie.cpp
 */
#include <iostream>
#include "boost/tuple/tuple.hpp"

int main(void)
{
    int a;
    std::string b;
    boost::tie(a, b) = boost::make_tuple(123, "yoshio");
    std::cout << a << ", " << b << std::endl;

    boost::tie(b, a) = boost::make_tuple("yoshio", 123);
    std::cout << a << ", " << b << std::endl;

    return 0;
}

これをアセンブラ展開すると、1200行ちょっとになる。
順番が違うから、それに応じたコードを生成するしかないのか。


では、同じtieの並びで変数が違ったらどうなる?

/*
 * $ g++ -o tst tietie.cpp
 */
#include <iostream>
#include "boost/tuple/tuple.hpp"

int main(void)
{
    int a;
    std::string b;
    boost::tie(a, b) = boost::make_tuple(123, "yoshio");
    std::cout << a << ", " << b << std::endl;

    int m;
    std::string n;
    boost::tie(m, n) = boost::make_tuple(123, "yoshio");
    std::cout << a << ", " << b << std::endl;

    return 0;
}

これは、750行程度だった。

変数mを、int型からuint8_t型に変更すると、972行。
uint64_tにしても同じだった。

C++のテンプレートは、基本的にマクロの拡張のようなものだったと思うので、uint8_tはint内に収まるから、途中は全部int型で処理して最後にキャストしてやろう、みたいなことはできないのだろう。

まあ、今回は最適化したわけでもないし、アセンブラにして眺めただけなので、違いは出てくるかもしれんが、コードサイズが大きくなることを心配するのであれば、そこら辺は実装側で気をつけねばならんだろうな。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。