Get first element of std::tuple satisfying trait
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 |
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 '18 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 '18 at 16:23
add a comment |
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 '18 at 19:58
max66
36.2k74165
36.2k74165
asked Nov 11 '18 at 16:02
tommaiseytommaisey
1358
1358
For me it is unclear what your question is. What is wrong withstd::get_if<float>(my_tuple)
?
– mkaes
Nov 11 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 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 '18 at 16:23
add a comment |
3 Answers
3
active
oldest
votes
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 '18 at 20:35
add a comment |
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 '18 at 20:08
add a comment |
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 |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
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
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
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 '18 at 20:35
add a comment |
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 '18 at 20:35
add a comment |
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 '18 at 22:58
OktalistOktalist
10k12848
10k12848
That's very nifty indeed!
– tommaisey
Nov 12 '18 at 20:35
add a comment |
That's very nifty indeed!
– tommaisey
Nov 12 '18 at 20:35
That's very nifty indeed!
– tommaisey
Nov 12 '18 at 20:35
That's very nifty indeed!
– tommaisey
Nov 12 '18 at 20:35
add a comment |
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 '18 at 20:08
add a comment |
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 '18 at 20:08
add a comment |
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 '18 at 19:57
max66max66
36.2k74165
36.2k74165
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 '18 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 '18 at 20:08
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 '18 at 20:08
Ah very nice! This is easier to extend than the solution I found. Thank you very much!
– tommaisey
Nov 11 '18 at 20:08
add a comment |
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 |
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 |
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 '18 at 18:02
tommaiseytommaisey
1358
1358
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.
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 '18 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 '18 at 16:23