1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

tupleの使い方メモ

Last updated at Posted at 2024-10-21

おことわり

クソ雑魚初心者のメモです.

問1

(Q)
A 型 N 個から成るよ.個数 N は静的に決まるよ.どう実装すればいいか?

(A)
それは単純に
A As[5]; //Aが5個 とか
std::array<A,3> As; //Aが3個 とかでいいんですかね.

(Q)
その場合,全ての要素についてメソッド A::F() 呼ぶには?

(A)
こんなすかね?
for( A &a : As )a.F();

問2

(Q)
A, B, C から成るよ.要素の個数と,何番目が何型なのかは静的に決まるよ.
例えば { A,A,B } とか { C,B,A,B,B } とか.どう実装すればいいか?

(A)
えっと…???
ああ,
std::tuple<A,A,B> とか std::tuple<C,B,A,B,B> とかでいいのか…な?

(Q)
その場合,全ての要素についてメソッド F() を呼ぶには?
A,B,C は全てメソッド F() を持つ型なのだとして)

(A)
んん???
すいません,わかりません.ググります……

(そして2時間後……)

なんか↓で動いた気がするけど……難しすぎない?

//---------------------------
//(*1)tupleの要素を先頭から順に引数として用いて Func を呼ぶ,というのを
//ググった結果,見様見真似で書いたもの

template< std::size_t TupleIndex=0, typename Func, typename... TupleItemTypes >
inline typename std::enable_if_t< TupleIndex == sizeof...(TupleItemTypes) >
Tuple_for_each( const std::tuple<TupleItemTypes...> &, Func & ){}

template< std::size_t TupleIndex=0, typename Func, typename... TupleItemTypes >
inline typename std::enable_if_t< TupleIndex < sizeof...(TupleItemTypes) >
Tuple_for_each( const std::tuple<TupleItemTypes...> &t, Func &f )
{
	f( std::get<TupleIndex>(t) );
	Tuple_for_each< TupleIndex+1, Func, TupleItemTypes...>( t, f );
}

//---------------------------

//A,B,C
struct A{	void F() const {	std::cout << "A ";	}	};
struct B{	void F() const {	std::cout << "B ";	}	};
struct C{	void F() const {	std::cout << "C ";	}	};

//
int main()
{
	//(*2)「ジェネリックラムダ」とかいう不可思議存在
	auto Func = [](auto &X){	X.F();	};

	{//{A,A,B}
		std::tuple<A,A,B> T;
		Tuple_for_each( T, Func );
	}
	std::cout << '\n';
	{//{C,B,A,B,B}
		std::tuple<C,B,A,B,B> T;
		Tuple_for_each( T, Func );
	}
}

(*1) のところ, 最初,自力で

template< std::size_t TupleIndex=0, typename Func, typename... TupleItemTypes >
void My_Tuple_for_each( const std::tuple<TupleItemTypes...> &t, Func &f )
{
	f( std::get<TupleIndex>(t) );

	if( TupleIndex+1 < std::tuple_size_v< std::tuple<TupleItemTypes...> > )
	{	My_Tuple_for_each< TupleIndex+1, Func, TupleItemTypes...>( t, f );	}
}

とか書いてみたんだけど,これだと
My_Tuple_for_each< TupleIndex+1, Func, TupleItemTypes...>( t, f ); で TupleIndex が範囲外のものを実体化しようとしてしまうのでダメであった.
enable_if だの何だのいうのを持ってくるのは馬鹿丸出し初心者には厳しいです.C++難しすぎ.

(*2)のところでは,Tuple_for_each を使おうにも「 Func には何を渡せばいいんだよ?」っていうのがまた謎であった.
あと,

//こうですか? わかりません><
std::tuple<A,A,B> T;
Tuple_for_each( T, [](auto &X){	X.F();	} );  //←コンパイルエラー

とか書いてコンパイル通らなくてしばらく躓いていたが,それは単に引数の型が Func & だからコレじゃ渡せないっていうだけの話だった.
Tuple_for_each をコピペして const Func & なやつも用意すれば良いのかな.)


追記

むむ?
自力で書いて失敗した My_Tuple_for_each についてだが,

if( TupleIndex+1 < std::tuple_size_v< std::tuple<TupleItemTypes...> > )

のところを if constexpr とすればいけるのではあるまいか…?

試してみたらOKっぽい雰囲気.

1
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?