if constexprと戻り値autoで型リストのfind実装
C++17ならわざわざテンプレートで再帰しなくても、if constexpr
と戻り値auto
で`見た目がわかりやすく楽に実装できるんじゃないかと思ったので書く。
別にfindじゃなくても良いけどなんとなく。
結果だけならリンク先で見れます。
http://melpon.org/wandbox/permlink/d26Nr2XNmPRIk5R3
実装
find実装に必要な型
type_list
とtype_holder
。
type_list
template <typename... Args>
struct type_list;
template <typename Head, typename... Tail>
struct type_list<Head, Tail...>
{
using head = Head;
using tail = type_list<Tail...>;
};
type_holder
template <typename T>
struct type_holder
{
using type = T;
};
findの実装
find
template <typename List, template <typename> typename F>
auto find()
{
using head = typename List::head;
if constexpr(F<head>::value)
{
return type_holder<head>{};
}
else
{
return find<typename List::tail, F>();
}
}
使う
main
int main()
{
using list = type_list<char, unsigned short, const long, double>;
using const_type = typename decltype(find<list, std::is_const>())::type; // const long
using unsigned_type = typename decltype(find<list, std::is_unsigned>())::type; // unsigned short
using floating_type = typename decltype(find<list, std::is_floating_point>())::type; // double
//using error_type = typename decltype(find<list, std::is_reference>())::type; // error
}
エラー時のことは特に考えてない。
終わりに
このような実装だとtype_holder
がないと見つけたい型にデフォルトコンストラクタが必要になる(はず)。
テンプレートで再起するよりだいぶ楽になった気がする
template <typename List, template <typename> typename F>
using find_t = typename decltype(find<List, F>())::type;
こんな感じのものを用意しておけば使う方もスッキリする。