Get first element of std::tuple satisfying trait










2















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).










share|improve this question
























  • 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
















2















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).










share|improve this question
























  • 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














2












2








2








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).










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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


















  • 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

















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













3 Answers
3






active

oldest

votes


















1














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.






share|improve this answer























  • That's very nifty indeed!

    – tommaisey
    Nov 12 '18 at 20:35


















1














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






share|improve this answer























  • Ah very nice! This is easier to extend than the solution I found. Thank you very much!

    – tommaisey
    Nov 11 '18 at 20:08


















0














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.






share|improve this answer






















    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
    );



    );













    draft saved

    draft discarded


















    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









    1














    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.






    share|improve this answer























    • That's very nifty indeed!

      – tommaisey
      Nov 12 '18 at 20:35















    1














    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.






    share|improve this answer























    • That's very nifty indeed!

      – tommaisey
      Nov 12 '18 at 20:35













    1












    1








    1







    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.






    share|improve 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.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 11 '18 at 22:58









    OktalistOktalist

    10k12848




    10k12848












    • 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





    That's very nifty indeed!

    – tommaisey
    Nov 12 '18 at 20:35













    1














    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






    share|improve this answer























    • Ah very nice! This is easier to extend than the solution I found. Thank you very much!

      – tommaisey
      Nov 11 '18 at 20:08















    1














    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






    share|improve this answer























    • Ah very nice! This is easier to extend than the solution I found. Thank you very much!

      – tommaisey
      Nov 11 '18 at 20:08













    1












    1








    1







    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






    share|improve this answer













    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







    share|improve this answer












    share|improve this answer



    share|improve this answer










    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

















    • 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











    0














    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.






    share|improve this answer



























      0














      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.






      share|improve this answer

























        0












        0








        0







        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.






        share|improve this answer













        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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 11 '18 at 18:02









        tommaiseytommaisey

        1358




        1358



























            draft saved

            draft discarded
















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

            Crossroads (UK TV series)

            ữḛḳṊẴ ẋ,Ẩṙ,ỹḛẪẠứụỿṞṦ,Ṉẍừ,ứ Ị,Ḵ,ṏ ṇỪḎḰṰọửḊ ṾḨḮữẑỶṑỗḮṣṉẃ Ữẩụ,ṓ,ḹẕḪḫỞṿḭ ỒṱṨẁṋṜ ḅẈ ṉ ứṀḱṑỒḵ,ḏ,ḊḖỹẊ Ẻḷổ,ṥ ẔḲẪụḣể Ṱ ḭỏựẶ Ồ Ṩ,ẂḿṡḾồ ỗṗṡịṞẤḵṽẃ ṸḒẄẘ,ủẞẵṦṟầṓế