Get first element of std::tuple satisfying trait
up vote
2
down vote
favorite
I'm using C++17. I'd like to get an element of a tuple that satisfies some type trait. It would be amazing if the trait could be supplied generically, but I'd be satisfied with a specific function for a certain trait. Usage might look something like this:
auto my_tuple = std::make_tuple 0.f, 1 ;
auto basic = get_if_integral (my_tuple);
auto fancy = get_if<std::is_floating_point> (my_tuple);
std::cout << basic; // '1'
std::cout << fancy; // '0.f'
Ideally this would fail to compile if more than one element satisfies the trait, like std::get (std::tuple)
.
c++ c++17 variadic-templates template-meta-programming stdtuple
add a comment |
up vote
2
down vote
favorite
I'm using C++17. I'd like to get an element of a tuple that satisfies some type trait. It would be amazing if the trait could be supplied generically, but I'd be satisfied with a specific function for a certain trait. Usage might look something like this:
auto my_tuple = std::make_tuple 0.f, 1 ;
auto basic = get_if_integral (my_tuple);
auto fancy = get_if<std::is_floating_point> (my_tuple);
std::cout << basic; // '1'
std::cout << fancy; // '0.f'
Ideally this would fail to compile if more than one element satisfies the trait, like std::get (std::tuple)
.
c++ c++17 variadic-templates template-meta-programming stdtuple
For me it is unclear what your question is. What is wrong withstd::get_if<float>(my_tuple)
?
– mkaes
Nov 11 at 16:20
That would be juststd::get<float> (my_tuple)
, I think. The context I'm using it is a little more complex, this is just an example. I have a tuple of tuples, and I want to return a reference to the first inner tuple that satisfies some trait.
– tommaisey
Nov 11 at 16:23
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I'm using C++17. I'd like to get an element of a tuple that satisfies some type trait. It would be amazing if the trait could be supplied generically, but I'd be satisfied with a specific function for a certain trait. Usage might look something like this:
auto my_tuple = std::make_tuple 0.f, 1 ;
auto basic = get_if_integral (my_tuple);
auto fancy = get_if<std::is_floating_point> (my_tuple);
std::cout << basic; // '1'
std::cout << fancy; // '0.f'
Ideally this would fail to compile if more than one element satisfies the trait, like std::get (std::tuple)
.
c++ c++17 variadic-templates template-meta-programming stdtuple
I'm using C++17. I'd like to get an element of a tuple that satisfies some type trait. It would be amazing if the trait could be supplied generically, but I'd be satisfied with a specific function for a certain trait. Usage might look something like this:
auto my_tuple = std::make_tuple 0.f, 1 ;
auto basic = get_if_integral (my_tuple);
auto fancy = get_if<std::is_floating_point> (my_tuple);
std::cout << basic; // '1'
std::cout << fancy; // '0.f'
Ideally this would fail to compile if more than one element satisfies the trait, like std::get (std::tuple)
.
c++ c++17 variadic-templates template-meta-programming stdtuple
c++ c++17 variadic-templates template-meta-programming stdtuple
edited Nov 11 at 19:58
max66
33.6k63762
33.6k63762
asked Nov 11 at 16:02
tommaisey
1317
1317
For me it is unclear what your question is. What is wrong withstd::get_if<float>(my_tuple)
?
– mkaes
Nov 11 at 16:20
That would be juststd::get<float> (my_tuple)
, I think. The context I'm using it is a little more complex, this is just an example. I have a tuple of tuples, and I want to return a reference to the first inner tuple that satisfies some trait.
– tommaisey
Nov 11 at 16:23
add a comment |
For me it is unclear what your question is. What is wrong withstd::get_if<float>(my_tuple)
?
– mkaes
Nov 11 at 16:20
That would be juststd::get<float> (my_tuple)
, I think. The context I'm using it is a little more complex, this is just an example. I have a tuple of tuples, and I want to return a reference to the first inner tuple that satisfies some trait.
– tommaisey
Nov 11 at 16:23
For me it is unclear what your question is. What is wrong with
std::get_if<float>(my_tuple)
?– mkaes
Nov 11 at 16:20
For me it is unclear what your question is. What is wrong with
std::get_if<float>(my_tuple)
?– mkaes
Nov 11 at 16:20
That would be just
std::get<float> (my_tuple)
, I think. The context I'm using it is a little more complex, this is just an example. I have a tuple of tuples, and I want to return a reference to the first inner tuple that satisfies some trait.– tommaisey
Nov 11 at 16:23
That would be just
std::get<float> (my_tuple)
, I think. The context I'm using it is a little more complex, this is just an example. I have a tuple of tuples, and I want to return a reference to the first inner tuple that satisfies some trait.– tommaisey
Nov 11 at 16:23
add a comment |
3 Answers
3
active
oldest
votes
up vote
1
down vote
accepted
Here's a surprisingly simple way without using recursion:
template <template <typename...> typename T, typename... Ts>
constexpr int index_of_integral(const T<Ts...>&)
const bool a = std::is_integral_v<Ts>... ;
for (int i = 0; i < sizeof...(Ts); ++i) if (a[i]) return i;
return -1;
template <typename T>
constexpr decltype(auto) get_if_integral(T&& t)
return std::get<index_of_integral(t)>(std::forward<T>(t));
int main()
constexpr auto t = std::make_tuple(3.14, 42, "xyzzy");
static_assert(get_if_integral(t) == 42);
It could easily be extended to be parametrized on the trait.
The only things that make it C++17 are the is_integral_v
variable template and the single-argument static_assert
. Everything else is C++14.
Note that in C++20 the for
loop could be replaced with std::find
and std::distance
.
Ideally it should throw an exception instead of returning -1, but compilers don't seem to like that.
Inspired by this answer.
That's very nifty indeed!
– tommaisey
Nov 12 at 20:35
add a comment |
up vote
1
down vote
If I understand correctly what you want... I propose an helper struct gf_h
("get first helper") as follows
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
and a couple of functions that use it:
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
Observe that are SFINAE enabled/disabled functions, so are enabled only if there is an integral (or float) value in the tuple
The following is a full compiling example
#include <tuple>
#include <iostream>
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
int main()
auto tup1 = std::make_tuple(3.f, 2., 1, 0);
std::cout << get_first_integral(tup1) << std::endl; // 1
std::cout << get_first_floating(tup1) << std::endl; // 3
auto tup2 = std::make_tuple("abc", 4, 5);
std::cout << get_first_integral(tup2) << std::endl; // 4
// std::cout << get_first_floating(tup2) << std::endl; // error
auto tup3 = std::make_tuple("xyz", 6., 7.f);
// std::cout << get_first_integral(tup3) << std::endl; // error
std::cout << get_first_floating(tup3) << std::endl; // 6
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 at 20:08
add a comment |
up vote
0
down vote
Ok, I figured out a way to accomplish this in a way that is not generic over the trait, but that's good enough for my current purpose. Using if constexpr
this really doesn't look too bad. I'm sure this isn't hugely idiomatic, but it works for me:
template <std::size_t Idx, typename... Us>
auto& get_if_integral_impl (std::tuple<Us...>& t)
static_assert (Idx < std::tuple_size_v<std::tuple<Us...>>,
"No integral elements in this tuple.");
if constexpr (std::is_integral<std::tuple_element_t<Idx, std::tuple<Us...>>>::value)
return std::get<Idx> (t);
else
return get_if_integral_impl<Idx + 1> (t);
template<typename... Us>
auto& get_if_integral (std::tuple<Us...>& t)
return get_if_integral_impl<0> (t);
auto tup = std::make_tuple (3.f, 2., 1, 0);
std::cout << get_if_integral (tup); // '1'
My use case is a little more complex, involving returning the first nested tuple which itself contains another type, but this should convey the basic idea.
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Here's a surprisingly simple way without using recursion:
template <template <typename...> typename T, typename... Ts>
constexpr int index_of_integral(const T<Ts...>&)
const bool a = std::is_integral_v<Ts>... ;
for (int i = 0; i < sizeof...(Ts); ++i) if (a[i]) return i;
return -1;
template <typename T>
constexpr decltype(auto) get_if_integral(T&& t)
return std::get<index_of_integral(t)>(std::forward<T>(t));
int main()
constexpr auto t = std::make_tuple(3.14, 42, "xyzzy");
static_assert(get_if_integral(t) == 42);
It could easily be extended to be parametrized on the trait.
The only things that make it C++17 are the is_integral_v
variable template and the single-argument static_assert
. Everything else is C++14.
Note that in C++20 the for
loop could be replaced with std::find
and std::distance
.
Ideally it should throw an exception instead of returning -1, but compilers don't seem to like that.
Inspired by this answer.
That's very nifty indeed!
– tommaisey
Nov 12 at 20:35
add a comment |
up vote
1
down vote
accepted
Here's a surprisingly simple way without using recursion:
template <template <typename...> typename T, typename... Ts>
constexpr int index_of_integral(const T<Ts...>&)
const bool a = std::is_integral_v<Ts>... ;
for (int i = 0; i < sizeof...(Ts); ++i) if (a[i]) return i;
return -1;
template <typename T>
constexpr decltype(auto) get_if_integral(T&& t)
return std::get<index_of_integral(t)>(std::forward<T>(t));
int main()
constexpr auto t = std::make_tuple(3.14, 42, "xyzzy");
static_assert(get_if_integral(t) == 42);
It could easily be extended to be parametrized on the trait.
The only things that make it C++17 are the is_integral_v
variable template and the single-argument static_assert
. Everything else is C++14.
Note that in C++20 the for
loop could be replaced with std::find
and std::distance
.
Ideally it should throw an exception instead of returning -1, but compilers don't seem to like that.
Inspired by this answer.
That's very nifty indeed!
– tommaisey
Nov 12 at 20:35
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Here's a surprisingly simple way without using recursion:
template <template <typename...> typename T, typename... Ts>
constexpr int index_of_integral(const T<Ts...>&)
const bool a = std::is_integral_v<Ts>... ;
for (int i = 0; i < sizeof...(Ts); ++i) if (a[i]) return i;
return -1;
template <typename T>
constexpr decltype(auto) get_if_integral(T&& t)
return std::get<index_of_integral(t)>(std::forward<T>(t));
int main()
constexpr auto t = std::make_tuple(3.14, 42, "xyzzy");
static_assert(get_if_integral(t) == 42);
It could easily be extended to be parametrized on the trait.
The only things that make it C++17 are the is_integral_v
variable template and the single-argument static_assert
. Everything else is C++14.
Note that in C++20 the for
loop could be replaced with std::find
and std::distance
.
Ideally it should throw an exception instead of returning -1, but compilers don't seem to like that.
Inspired by this answer.
Here's a surprisingly simple way without using recursion:
template <template <typename...> typename T, typename... Ts>
constexpr int index_of_integral(const T<Ts...>&)
const bool a = std::is_integral_v<Ts>... ;
for (int i = 0; i < sizeof...(Ts); ++i) if (a[i]) return i;
return -1;
template <typename T>
constexpr decltype(auto) get_if_integral(T&& t)
return std::get<index_of_integral(t)>(std::forward<T>(t));
int main()
constexpr auto t = std::make_tuple(3.14, 42, "xyzzy");
static_assert(get_if_integral(t) == 42);
It could easily be extended to be parametrized on the trait.
The only things that make it C++17 are the is_integral_v
variable template and the single-argument static_assert
. Everything else is C++14.
Note that in C++20 the for
loop could be replaced with std::find
and std::distance
.
Ideally it should throw an exception instead of returning -1, but compilers don't seem to like that.
Inspired by this answer.
answered Nov 11 at 22:58
Oktalist
9,85212648
9,85212648
That's very nifty indeed!
– tommaisey
Nov 12 at 20:35
add a comment |
That's very nifty indeed!
– tommaisey
Nov 12 at 20:35
That's very nifty indeed!
– tommaisey
Nov 12 at 20:35
That's very nifty indeed!
– tommaisey
Nov 12 at 20:35
add a comment |
up vote
1
down vote
If I understand correctly what you want... I propose an helper struct gf_h
("get first helper") as follows
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
and a couple of functions that use it:
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
Observe that are SFINAE enabled/disabled functions, so are enabled only if there is an integral (or float) value in the tuple
The following is a full compiling example
#include <tuple>
#include <iostream>
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
int main()
auto tup1 = std::make_tuple(3.f, 2., 1, 0);
std::cout << get_first_integral(tup1) << std::endl; // 1
std::cout << get_first_floating(tup1) << std::endl; // 3
auto tup2 = std::make_tuple("abc", 4, 5);
std::cout << get_first_integral(tup2) << std::endl; // 4
// std::cout << get_first_floating(tup2) << std::endl; // error
auto tup3 = std::make_tuple("xyz", 6., 7.f);
// std::cout << get_first_integral(tup3) << std::endl; // error
std::cout << get_first_floating(tup3) << std::endl; // 6
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 at 20:08
add a comment |
up vote
1
down vote
If I understand correctly what you want... I propose an helper struct gf_h
("get first helper") as follows
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
and a couple of functions that use it:
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
Observe that are SFINAE enabled/disabled functions, so are enabled only if there is an integral (or float) value in the tuple
The following is a full compiling example
#include <tuple>
#include <iostream>
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
int main()
auto tup1 = std::make_tuple(3.f, 2., 1, 0);
std::cout << get_first_integral(tup1) << std::endl; // 1
std::cout << get_first_floating(tup1) << std::endl; // 3
auto tup2 = std::make_tuple("abc", 4, 5);
std::cout << get_first_integral(tup2) << std::endl; // 4
// std::cout << get_first_floating(tup2) << std::endl; // error
auto tup3 = std::make_tuple("xyz", 6., 7.f);
// std::cout << get_first_integral(tup3) << std::endl; // error
std::cout << get_first_floating(tup3) << std::endl; // 6
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 at 20:08
add a comment |
up vote
1
down vote
up vote
1
down vote
If I understand correctly what you want... I propose an helper struct gf_h
("get first helper") as follows
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
and a couple of functions that use it:
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
Observe that are SFINAE enabled/disabled functions, so are enabled only if there is an integral (or float) value in the tuple
The following is a full compiling example
#include <tuple>
#include <iostream>
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
int main()
auto tup1 = std::make_tuple(3.f, 2., 1, 0);
std::cout << get_first_integral(tup1) << std::endl; // 1
std::cout << get_first_floating(tup1) << std::endl; // 3
auto tup2 = std::make_tuple("abc", 4, 5);
std::cout << get_first_integral(tup2) << std::endl; // 4
// std::cout << get_first_floating(tup2) << std::endl; // error
auto tup3 = std::make_tuple("xyz", 6., 7.f);
// std::cout << get_first_integral(tup3) << std::endl; // error
std::cout << get_first_floating(tup3) << std::endl; // 6
If I understand correctly what you want... I propose an helper struct gf_h
("get first helper") as follows
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
and a couple of functions that use it:
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
Observe that are SFINAE enabled/disabled functions, so are enabled only if there is an integral (or float) value in the tuple
The following is a full compiling example
#include <tuple>
#include <iostream>
template <std::size_t, bool ...>
struct gf_h
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, false, Bs...> : public gf_h<I+1u, Bs...>
;
template <std::size_t I, bool ... Bs>
struct gf_h<I, true, Bs...> : public std::integral_constant<std::size_t, I>
;
template <typename ... Us,
std::size_t I = gf_h<0, std::is_integral<Us>::value...>::value>
auto get_first_integral (std::tuple<Us...> const & t)
return std::get<I>(t);
template <typename ... Us,
std::size_t I = gf_h<0, std::is_floating_point<Us>::value...>::value>
auto get_first_floating (std::tuple<Us...> const & t)
return std::get<I>(t);
int main()
auto tup1 = std::make_tuple(3.f, 2., 1, 0);
std::cout << get_first_integral(tup1) << std::endl; // 1
std::cout << get_first_floating(tup1) << std::endl; // 3
auto tup2 = std::make_tuple("abc", 4, 5);
std::cout << get_first_integral(tup2) << std::endl; // 4
// std::cout << get_first_floating(tup2) << std::endl; // error
auto tup3 = std::make_tuple("xyz", 6., 7.f);
// std::cout << get_first_integral(tup3) << std::endl; // error
std::cout << get_first_floating(tup3) << std::endl; // 6
answered Nov 11 at 19:57
max66
33.6k63762
33.6k63762
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 at 20:08
add a comment |
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 at 20:08
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 at 20:08
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 at 20:08
add a comment |
up vote
0
down vote
Ok, I figured out a way to accomplish this in a way that is not generic over the trait, but that's good enough for my current purpose. Using if constexpr
this really doesn't look too bad. I'm sure this isn't hugely idiomatic, but it works for me:
template <std::size_t Idx, typename... Us>
auto& get_if_integral_impl (std::tuple<Us...>& t)
static_assert (Idx < std::tuple_size_v<std::tuple<Us...>>,
"No integral elements in this tuple.");
if constexpr (std::is_integral<std::tuple_element_t<Idx, std::tuple<Us...>>>::value)
return std::get<Idx> (t);
else
return get_if_integral_impl<Idx + 1> (t);
template<typename... Us>
auto& get_if_integral (std::tuple<Us...>& t)
return get_if_integral_impl<0> (t);
auto tup = std::make_tuple (3.f, 2., 1, 0);
std::cout << get_if_integral (tup); // '1'
My use case is a little more complex, involving returning the first nested tuple which itself contains another type, but this should convey the basic idea.
add a comment |
up vote
0
down vote
Ok, I figured out a way to accomplish this in a way that is not generic over the trait, but that's good enough for my current purpose. Using if constexpr
this really doesn't look too bad. I'm sure this isn't hugely idiomatic, but it works for me:
template <std::size_t Idx, typename... Us>
auto& get_if_integral_impl (std::tuple<Us...>& t)
static_assert (Idx < std::tuple_size_v<std::tuple<Us...>>,
"No integral elements in this tuple.");
if constexpr (std::is_integral<std::tuple_element_t<Idx, std::tuple<Us...>>>::value)
return std::get<Idx> (t);
else
return get_if_integral_impl<Idx + 1> (t);
template<typename... Us>
auto& get_if_integral (std::tuple<Us...>& t)
return get_if_integral_impl<0> (t);
auto tup = std::make_tuple (3.f, 2., 1, 0);
std::cout << get_if_integral (tup); // '1'
My use case is a little more complex, involving returning the first nested tuple which itself contains another type, but this should convey the basic idea.
add a comment |
up vote
0
down vote
up vote
0
down vote
Ok, I figured out a way to accomplish this in a way that is not generic over the trait, but that's good enough for my current purpose. Using if constexpr
this really doesn't look too bad. I'm sure this isn't hugely idiomatic, but it works for me:
template <std::size_t Idx, typename... Us>
auto& get_if_integral_impl (std::tuple<Us...>& t)
static_assert (Idx < std::tuple_size_v<std::tuple<Us...>>,
"No integral elements in this tuple.");
if constexpr (std::is_integral<std::tuple_element_t<Idx, std::tuple<Us...>>>::value)
return std::get<Idx> (t);
else
return get_if_integral_impl<Idx + 1> (t);
template<typename... Us>
auto& get_if_integral (std::tuple<Us...>& t)
return get_if_integral_impl<0> (t);
auto tup = std::make_tuple (3.f, 2., 1, 0);
std::cout << get_if_integral (tup); // '1'
My use case is a little more complex, involving returning the first nested tuple which itself contains another type, but this should convey the basic idea.
Ok, I figured out a way to accomplish this in a way that is not generic over the trait, but that's good enough for my current purpose. Using if constexpr
this really doesn't look too bad. I'm sure this isn't hugely idiomatic, but it works for me:
template <std::size_t Idx, typename... Us>
auto& get_if_integral_impl (std::tuple<Us...>& t)
static_assert (Idx < std::tuple_size_v<std::tuple<Us...>>,
"No integral elements in this tuple.");
if constexpr (std::is_integral<std::tuple_element_t<Idx, std::tuple<Us...>>>::value)
return std::get<Idx> (t);
else
return get_if_integral_impl<Idx + 1> (t);
template<typename... Us>
auto& get_if_integral (std::tuple<Us...>& t)
return get_if_integral_impl<0> (t);
auto tup = std::make_tuple (3.f, 2., 1, 0);
std::cout << get_if_integral (tup); // '1'
My use case is a little more complex, involving returning the first nested tuple which itself contains another type, but this should convey the basic idea.
answered Nov 11 at 18:02
tommaisey
1317
1317
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53250540%2fget-first-element-of-stdtuple-satisfying-trait%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
For me it is unclear what your question is. What is wrong with
std::get_if<float>(my_tuple)
?– mkaes
Nov 11 at 16:20
That would be just
std::get<float> (my_tuple)
, I think. The context I'm using it is a little more complex, this is just an example. I have a tuple of tuples, and I want to return a reference to the first inner tuple that satisfies some trait.– tommaisey
Nov 11 at 16:23