c++ - C++11: how to write a template function that works like get<tuple>... but receives param pack? -
i know in c++11, get<> template function works std::tuple indexed value of tuple, resolved @ compile time.
but requirement have template function called get<> receives parameter pack, code should below:
#include<iostream> using namespace std; template<typename head, typename ... tail> auto get(size_t index, head&& t, tail&&...tail){ return get(index-1, tail...); } template<typename head, typename ... tail> head get<0>(head&& t, tail&&...tail){ return t; } int main(){ cout<<get(3,"abc",'x',27,"hello")<<endl; cout<<get(2,"abc",'x',28,"hello")<<endl; return 0; }
well doesn't compile, sure, don't know how write such "get" template function. wish main function run , print below:
hello 28
so question: how implement "get" template mentioned above? thanks!
do really need able select index @ runtime? if not, following should enough:
template <std::size_t index, typename ...p> auto get(p &&... params) { return std::get<index>(std::make_tuple(params...)); } // ... std::cout << get<1>("abc", 42, 123.456); // prints 42
if indeed want have index normal (runtime) parameter, you'd have return std::variant<p...>
(or std::any
, or tagged union), since return type can't depend on runtime parameter.
a possible implementation this:
template <typename ...p> std::variant<p...> get(std::size_t index, p &&... params) { std::size_t pos = 0; std::variant<p...> ret; ((index == pos++ ? void(ret = params) : void()) , ...); return ret; } // ... std::cout << std::get<int>( get(1, "abc", 42, 123.456) ); // prints 42 too, looks ugly
or specify return type template parameter:
template <typename t, typename ...p> t get(std::size_t index, p &&... params) { std::size_t pos = 0; std::variant<p...> va; ((index == pos++ ? void(va = params) : void()) , ...); if (t *ptr = std::get_if<t>(va)) return t; else throw /*something*/; } // ... std::cout << get<int>(1, "abc", 42, 123.456); // 42
or pass value function/functor instead: (thanks @yakk)
template <typename t, typename ...p> void get(std::size_t index, t &&func, p &&... params) { std::size_t pos = 0; ((index == pos++ ? void(func(params)) : void()) , ...); } // ... get(1, [](int x){std::cout << x;}, "abc", 42, 123.456); // 42 // alternative: // get(1, [](auto x){std::cout << x;}, "abc", 42, 123.456); // 42 too, // print type can printed without having // specify type manually.
Comments
Post a Comment