#Filtering tuples with lambda function

134 messages · Page 1 of 1 (latest)

hidden bay
#

I have a task in my HW that require me to create a method that takes a tuple and a lambda function, applies this lambda function on each element of the tuple. at the end the method should return a new tuple containning the elements that returned true in lambda.

This is my tuple in main that i am filtering:

int main(){
        auto tpl = make_tuple(
                [](auto a, auto b) { return a + b; },
                10,
                25,
                42.42,
                "Hello",
                string("there")
        );
        
        auto tpl_type_filtered = filterTuple(tpl, []<typename T>(const T&) { return is_integral_v<T>; } );
        return 0;
} 

This is my progress so far:

template <size_t Index = 0, typename... Types,typename... Types2, typename Func>
auto filterTupleHelper(const std::tuple<Types...>& tuple, const Func& func, const std::tuple<Types2...>& container) {
    if constexpr (Index < sizeof...(Types)) {
        if constexpr (func(std::get<Index>(tuple))) {
            return filterTupleHelper<Index + 1>(tuple, func, std::tuple_cat(container, std::make_tuple(std::get<Index>(tuple))));
        } else {
            return filterTupleHelper<Index + 1>(tuple, func, container);
        }
    } else {
        return container;
    }
}

template <typename Tuple, typename Func>
auto filterTuple(const Tuple& tuple, const Func& func) {
    return filterTupleHelper(tuple, func, std::make_tuple());
}

Also the teacher requested the following:
" this function must be protected by a "requires" clause so that it will be only available for tuple params alo "concept" core language keyword usage is FORBIDDEN.
You must use inline requires expressions and clauses.
You can write your own is_tuple/is_tuple_v structs if necessary"

but i dont know why or how to use requires in this case, and i dont get what concept would benifit me. I feel like i am completely lost or missing the point..
I would really apprecaite some help

dull mauveBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.

mellow briar
#

which function exactly do they want to have a "requires"

hidden bay
#

i think the filter itself

wide mountain
#

Do we have constexpr lambdas yet? I don't remember.

hidden bay
#

but i didnt even know why i would use it in this case

mellow briar
#

which function exactly in your example

hidden bay
#

filterTuple

#

it was supposed to be 1 single function but i implemented 2 functions to apply my logic

#

but my logic is not working

mellow briar
#

yes constexpr lambdas exist atleast in c++20 iirc

hidden bay
#

and i am using 20

#

idk if you can understand my logic but

#

its i make a container and pass it the helper, helper iterates over each index, if func(element) is true i create a new container which is old cont+new container that has that element

mellow briar
#

ive never had to apply a requires to a lambda, and i dont understand this assignment

hidden bay
#

i keep repeating until no more elements exist

#

he gave us a hint but i also didnt understand it

mellow briar
#

they want you to check if each lambda element you pass to the function is a... lambda element?

wary hearth
wary hearth
#

you constrained filter tuple to only work on tuple

mellow briar
#

template <typename Tuple, typename Func> auto filterTuple(const Tuple& tuple, const Func& func) { return filterTupleHelper(tuple, func, std::make_tuple()); } is this the function you want to constrain?

wary hearth
#

you did it "wrong" by not following instructions on how to do that

#

currently your filterTuple sort of takes anything as first argument

#

but it doesn't actually allow anything in, because you forward that argument into your helper that explicitly does not allow anything that isn't a specialization of std::tuple

#

which is not what the instructions were requiring you to do

wary hearth
#

so yes

hidden bay
#

auto filterTupleHelper(const std::tuple<Types...>& tuple,

#

you mean this

wary hearth
#

well, that's the first argument of your helper

#

and it has to be a specialization of std::tuple because of how you've set it up

#

but again that doesn't follow the instructions

hidden bay
#

should i start from scratch

#

i thought my logic atleast is correct but its not working at all

wary hearth
#

I haven't actually read the rest of what you wrote

mellow briar
#

lol i am also lost. is the problem that your logic is not working or that you dont know how to smack on a requires on this

wary hearth
#

checked what you wrote, you don't need to start from scratch I would say

hidden bay
#

fuck require i can deal with it later

wary hearth
#

but if you feel like you need to reset yourself you could restart

hidden bay
#

just logic wise i cannot figure it out at all

#

i want to be able to call this function with a tuple and a function, and return a new tuple with elements that passed the test of the function

hidden bay
mellow briar
#

id start over if you have no clue whats wrong =P

hidden bay
#

i will do that i guess

wary hearth
#

because it almost definitely will not compile

#

because the way you used constant expression is wrong

#

which is a different problem from just the pure logic of what you're trying to achieve

#

like this if constexpr (func(std::get<Index>(tuple))) has no change to work because tuple is not usable in a constant expression

#

nor func

#

actually the more I think about this, the weirder it sounds

hidden bay
#

idk man i am starting from scratch

hidden bay
wary hearth
#

what sort of homework/course/uni are you in that already teaches c++20 and forces you to work on that kind of constexpr stuff

#

no, it's not easy

hidden bay
#

its advanced c++

#

elective course i am taking as an ug

wary hearth
#

if the type of your returned tuple depends on the predicate being satisfied, you're basically forced into nttp

hidden bay
#

class mixed with master students and its pretty fucking hardcore

#

nttp?

wary hearth
#

yeah so if you do not know what those are, you're sort of screwed

#

non-type template parameters

hidden bay
#

i might have missed a class

#

ill check if it was given before

wary hearth
#

what's your exact homework instruction/prompt for this function you need to write

mellow briar
#

what youre gonna have to do is make a function that appends one element to a tuple, then you can if constexpr branch on thhe result of the tuple element evalutaiton function to either append that element or recursively call filter on the next element index

wary hearth
#

the type of the "function" depends on the "input" value

#

the only way to get that to work is if the "input" value is a constant expression you can stuff as template parameter

#

unless the return type doesn't actually depend on the value, and you're meant to return a tuple with different values where the predicate wasn't satisfied

wary hearth
mellow briar
#

oh the value does not even matter here

wary hearth
#

what I was talking about was if you need something like

auto is_even = [](auto value) { return value % 2 == 0; };
auto result = filterTuple(std::make_tuple(0, 1, 2, 3), is_even);

then this has no chance of working if you don't understand how to use values as template arguments

#

aka nttp's

mellow briar
#

that tuple isnt gonna be constexpr

#

but if its just the type he checks it should work?

wary hearth
#

it can work but he'll have to make some amendment to his implementation

hidden bay
#

it shouldnt be just type, it should be based on the lambda

#

if lambda is true then that element should be added

mellow briar
#

ah then as sly said, youre gonna have to pass it as a template parameter value

wary hearth
#

then there's a whole bunch of things you do not know that is required to get this to work

#

also strings will pretty much not be supported

hidden bay
#

man fml what can i do

wary hearth
#

by that I mean specifically std::string

hidden bay
#

i can work with const char *

wary hearth
#

there's an argument for supporting other kind of strings

mellow briar
#

this has gone into the "probably not worth it " territory lol

wary hearth
#

there are restrictions for those as well technically, cause a char const* as nttp cannot refer to a string literal

#

unless they changed that rule

#

I'll admit I don't exactly check that specific rule all the time

#

and how it changes/does not change

#

but the basic thing is still that you need to know how to use nttp's

#

which isn't the end of the world, but still awkward/weird if you've never done it before

#

the most common/well-known example being the size of an std::array

#

std::array<int, 10> uses an nttp as second parameter

#

you passed in a value

#

that value, as a template parameter, can be used to change the return type of a template function

#

which is something you need to be able to do for this homework

wary hearth
#

unless I misunderstood what the homework was about

hidden bay
#

i did something

#

its not working but logically should be 100% true

#
template<int Index = 0,typename ...Args>
auto filterhelper(std::tuple<Args...> tpl,auto func,auto container){
    if constexpr (Index < sizeof...(Args)) {
        if(func(std::get<Index>(tpl))){
            auto newElementtuple= make_tuple<decltype(std::get<Index>(tpl))>(std::get<Index>(tpl));
            auto newContainer=std::tuple_cat(container,newElementtuple);
            return filterhelper<Index+1>(tpl,func,newContainer);
        }
    }
    else{
        return container;
    }
    return filterhelper<Index+1>(tpl,func,container);
}

auto filtertuple(const auto& tpl,const auto& func){
    return filterhelper<0>(tpl,func,std::make_tuple<>());

}```
#

almost same approach just cleaned it up i think

#

i fucking hate mylife man

wary hearth
#

;asm -std=c++20

template <int I>
auto foo()
{
  if constexpr (I % 2 == 0)
    return 0.0f;
  else
    return 0u;
}

#include <type_traits>
static_assert(std::is_same_v<decltype(foo<0>()), float>);
static_assert(std::is_same_v<decltype(foo<1>()), unsigned>);
mild heraldBOT
#
Compilation successful

No assembly generated.

mellow briar
#

problem is i dont think std tuple is supported as a nttp

hidden bay
#

i get this error : fatal error: template instantiation depth exceeds maximum of 900

#

its fatal i have never seen this

#

be cautious please

wary hearth
wary hearth
#

probably works at least

wary hearth
#

because the return type of a template function cannot change based on runtime values

#

because it's still a function at the end

#

what do you think should happen if your if constexpr evals true but the if nested in it evals true/false

hidden bay
#

is there any suggestions what to do

#

how do you filter a tuple, its impossible that this doesnt exist on the internet

wary hearth
#

I guess to make it more obvious you'd rewrite the thing as

template<int Index = 0,typename ...Args>
auto filterhelper(std::tuple<Args...> tpl,auto func,auto container){
    if constexpr (!Index < sizeof...(Args)) {
        return container;
    }
    else {
        if(func(std::get<Index>(tpl))){
            auto newElementtuple= make_tuple<decltype(std::get<Index>(tpl))>(std::get<Index>(tpl));
            auto newContainer=std::tuple_cat(container,newElementtuple);
            return filterhelper<Index+1>(tpl,func,newContainer);
        }
        else{
            return filterhelper<Index+1>(tpl,func,container);
        }
    }
}
#

I told you, you go and learn how to deal with nttp

#

and the restrictions on constant expressions

#

vs function parameters

hidden bay
#

this compiles but it always returns empty container, it never reach else statement

#

i tried to change position of ! in the if but it creates a new error on filterhelper<Index+1> line

wary hearth
#

I never said what I just posted would work

#

more like, I was saying it wouldn't work

wary hearth
dull mauveBOT
#

@hidden bay Has your question been resolved? If so, run !solved :)