• Lambda in STL compare

    From [email protected]@21:1/5 to All on Mon Oct 7 07:32:02 2024
    Isn't it about time that lambda functions could be used directly as STL comparitors instead of it being an ugly 2 step process?

    ie instead of:

    auto comp = [](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    };
    map<string,int,decltype(comp)> m(comp);

    which is no simpler than just using a functor, why can't we just do:

    map<string,int,[](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    }) m;

    I'm sure updating the compilers so a lambda could be a template parameter wouldn't be beyond the wit of man.

    Rather than adding esoteric functionality no one uses wouldn't it be better
    to tidy up what there is already?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to [email protected] on Mon Oct 7 10:16:46 2024
    On 07/10/2024 09:32, [email protected] wrote:
    Isn't it about time that lambda functions could be used directly as STL comparitors instead of it being an ugly 2 step process?

    ie instead of:

    auto comp = [](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    };
    map<string,int,decltype(comp)> m(comp);

    which is no simpler than just using a functor, why can't we just do:

    map<string,int,[](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    }) m;

    I'm sure updating the compilers so a lambda could be a template parameter wouldn't be beyond the wit of man.

    Rather than adding esoteric functionality no one uses wouldn't it be better to tidy up what there is already?


    After fixing the typos (you missed part of the "decltype"), it compiles
    fine:

    map<string, int, decltype([](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(), s2.c_str()) < 0;
    m;


    (Warning - I've only compiled this on godbolt, not tested it to see if
    it works!)


    The key point is that in C++20, lambda closures got a default
    constructor if they have no captures.

    It would, however, be even nicer if there were no need for "decltype" here.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Mon Oct 7 09:32:52 2024
    On Mon, 7 Oct 2024 10:12:03 +0200
    Bonita Montero <[email protected]> boring babbled:
    Am 07.10.2024 um 09:32 schrieb [email protected]:
    Isn't it about time that lambda functions could be used directly as STL
    comparitors instead of it being an ugly 2 step process?

    ie instead of:

    auto comp = [](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    };
    map<string,int,decltype(comp)> m(comp);

    which is no simpler than just using a functor, why can't we just do:

    map<string,int,[](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    }) m;

    I'm sure updating the compilers so a lambda could be a template parameter
    wouldn't be beyond the wit of man.

    Rather than adding esoteric functionality no one uses wouldn't it be better >> to tidy up what there is already?


    Lambdas can be used in an unevaluated context since C++20, i.e
    you could write <, decltype([]( ... ) { })> as you did. Try it
    with -std=c++20 / -std:c++29.

    I did, didn't work. But then the version of clang in MacOS is always behind
    the times. It supports the -std=c++20 option but doesn't seem to honour all
    of the 2020 spec yet.

    Anyway, good to know thats been sorted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Sam@21:1/5 to [email protected] on Mon Oct 7 07:35:34 2024
    [email protected] writes:

    which is no simpler than just using a functor, why can't we just do:

    map<string,int,[](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    }) m;

    I'm sure updating the compilers so a lambda could be a template parameter wouldn't be beyond the wit of man.

    The reason we cannot do that is because the third parameter to std::map is a type, and not an object. A lambda expression is an instance of an anonymous type, and not a type in of itself.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Mon Oct 7 14:06:41 2024
    On Mon, 07 Oct 2024 07:35:34 -0400
    Sam <[email protected]> boring babbled:
    [email protected] writes:

    which is no simpler than just using a functor, why can't we just do:

    map<string,int,[](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    }) m;

    I'm sure updating the compilers so a lambda could be a template parameter
    wouldn't be beyond the wit of man.

    The reason we cannot do that is because the third parameter to std::map is a >type, and not an object. A lambda expression is an instance of an anonymous >type, and not a type in of itself.

    Its a definition, not a value, so why can't it silently be converted internally by the compiler? Presumably it does just that when it sees decltype anyway.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrey Tarasevich@21:1/5 to [email protected] on Mon Oct 7 07:17:32 2024
    On 10/07/24 12:32 AM, [email protected] wrote:
    Isn't it about time that lambda functions could be used directly as STL comparitors instead of it being an ugly 2 step process?

    ie instead of:

    auto comp = [](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    };
    map<string,int,decltype(comp)> m(comp);

    which is no simpler than just using a functor, why can't we just do:

    map<string,int,[](const string &s1, const string &s2)
    {
    return strcasecmp(s1.c_str(),s2.c_str()) < 0;
    }) m;

    I'm sure updating the compilers so a lambda could be a template parameter wouldn't be beyond the wit of man.

    Firstly, the suggested resolution does not make any sense. Lambda
    expression produces a value. Why are you stuffing into a location that
    expects a type?

    Secondly, the language already provides a promising _potential_
    solution: class template deduction. Which means that theoretically one
    might dream about being able to do

    std::map<std::string, int> m(comp);

    without having to specify the type of `comp` in the template argument
    list, i.e. expecting the compiler to deduce the proper comparator type.

    However, firstly, at this time the deduction kicks only when no template argument is specified for the template. I.e. there's no partial
    deduction. And, secondly, this clashes with the current specification of `std::map`, which provides the default argument for the comparator
    parameter (as `std::less`).

    But even today you can do this:

    template <typename C>
    using si_map = std::map<std::string, int, C>;

    si_map m(comp);

    and it works.

    Maybe in the future class template parameter deduction will become more flexible... Or maybe there's a more elegant workaround to enable
    something like that today, which I just don't see.

    --
    Best regards,
    Andrey

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Mon Oct 7 14:53:08 2024
    On Mon, 7 Oct 2024 16:13:48 +0200
    Bonita Montero <[email protected]> boring babbled:
    Am 07.10.2024 um 16:06 schrieb [email protected]:

    Its a definition, not a value, ...

    Wrong, a lambda is a PR-value.

    I don't see why it can't be cast to std::function. It is a function after all.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Mon Oct 7 15:46:08 2024
    On Mon, 7 Oct 2024 17:06:11 +0200
    Bonita Montero <[email protected]> boring babbled:
    Am 07.10.2024 um 16:53 schrieb [email protected]:
    On Mon, 7 Oct 2024 16:13:48 +0200
    Bonita Montero <[email protected]> boring babbled:
    Am 07.10.2024 um 16:06 schrieb [email protected]:

    Its a definition, not a value, ...

    Wrong, a lambda is a PR-value.

    I don't see why it can't be cast to std::function. It is a function after >all.

    Of course you can cast it to a compatible function, i.e. the parmeters
    of the lambda and the parameter supplied to the function must match.

    The compiler knows exactly what the parameters are. Try thinking outside
    of the box. The semantic rules are not immutable laws of physics.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Tue Oct 8 08:23:45 2024
    On Mon, 7 Oct 2024 17:55:14 +0200
    Bonita Montero <[email protected]> boring babbled:
    Am 07.10.2024 um 17:46 schrieb [email protected]:

    The compiler knows exactly what the parameters are. ..

    The parameters of a function-object must be convertible to
    those of the lambda. That's all.

    So make it convertable. I find it perverse that the declaration of a struct/ class and the declaration of a function/lambda are considered different types of declarations. The compiler should see that its being used in a template and act accordingly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Tue Oct 8 10:24:32 2024
    On Tue, 8 Oct 2024 10:25:33 +0200
    Bonita Montero <[email protected]> boring babbled:
    Am 08.10.2024 um 10:23 schrieb [email protected]:

    So make it convertable. I find it perverse that the declaration of a struct/ >> class and the declaration of a function/lambda are considered different types

    of declarations. ..


    In one case you have a variable-_defintiion_, in the other a declaration.

    No, they're both declarations. The only difference is how you assign them
    to variables.

    [](whatever) { }

    is not a variable, its a definition.

    auto lambda = [](whatever) { }

    is a variable declaration and assignment.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Sam@21:1/5 to [email protected] on Tue Oct 8 08:25:33 2024
    [email protected] writes:

    On Mon, 07 Oct 2024 07:35:34 -0400
    Sam <[email protected]> boring babbled:
    The reason we cannot do that is because the third parameter to std::map is a >type, and not an object. A lambda expression is an instance of an anonymous >type, and not a type in of itself.

    Its a definition, not a value, so why can't it silently be converted internally
    by the compiler? Presumably it does just that when it sees decltype anyway.

    Because it's not the compiler's job to invent new templates. If there was an overloaded template whose third parameter is an object, then, I suppose,
    things will work this way. But there isn't one.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Tue Oct 8 14:44:48 2024
    On Tue, 08 Oct 2024 08:25:33 -0400
    Sam <[email protected]> boring babbled:
    [email protected] writes:

    On Mon, 07 Oct 2024 07:35:34 -0400
    Sam <[email protected]> boring babbled:
    The reason we cannot do that is because the third parameter to std::map is a

    type, and not an object. A lambda expression is an instance of an anonymous >> >type, and not a type in of itself.

    Its a definition, not a value, so why can't it silently be converted
    internally
    by the compiler? Presumably it does just that when it sees decltype anyway.

    Because it's not the compiler's job to invent new templates. If there was an

    Its the compilers job to interpret the template. Given the semantic hoops, gotchas,hacks and generalinconsistencies C++ already has, another one that might actually be useful isn't going to hurt.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Sam@21:1/5 to [email protected] on Tue Oct 8 17:52:25 2024
    [email protected] writes:

    On Tue, 08 Oct 2024 08:25:33 -0400
    Sam <[email protected]> boring babbled:

    Because it's not the compiler's job to invent new templates. If there was an

    Its the compilers job to interpret the template. Given the semantic hoops, gotchas,hacks and generalinconsistencies C++ already has, another one that might actually be useful isn't going to hurt.

    Hm, I'm beginning to think you're right. After all, C++ has always had a reputation of being too simplistic, straightforward, and easy to learn and understand. It's about time some complexity was added to the language.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Wed Oct 9 07:15:03 2024
    On Tue, 08 Oct 2024 17:52:25 -0400
    Sam <[email protected]> boring babbled:
    [email protected] writes:

    On Tue, 08 Oct 2024 08:25:33 -0400
    Sam <[email protected]> boring babbled:

    Because it's not the compiler's job to invent new templates. If there was an


    Its the compilers job to interpret the template. Given the semantic hoops, >> gotchas,hacks and generalinconsistencies C++ already has, another one that >> might actually be useful isn't going to hurt.

    Hm, I'm beginning to think you're right. After all, C++ has always had a >reputation of being too simplistic, straightforward, and easy to learn and >understand. It's about time some complexity was added to the language.

    I happen to think the removal of the need for decltype() would actually simplify things. Are there any instances where a piece of code would compile with and without decltype but otherwise is identical? If not then what harm would it do to make the compiler infer its a type instead of having to
    be explicily told? After all, thats the rationale behind "auto".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Wed Oct 9 07:16:40 2024
    On Tue, 08 Oct 2024 17:52:25 -0400
    Sam <[email protected]> boring babbled:
    [email protected] writes:

    On Tue, 08 Oct 2024 08:25:33 -0400
    Sam <[email protected]> boring babbled:

    Because it's not the compiler's job to invent new templates. If there was an


    Its the compilers job to interpret the template. Given the semantic hoops, >> gotchas,hacks and generalinconsistencies C++ already has, another one that >> might actually be useful isn't going to hurt.

    Hm, I'm beginning to think you're right. After all, C++ has always had a >reputation of being too simplistic, straightforward, and easy to learn and >understand. It's about time some complexity was added to the language.

    That horse bolted and disappeared over the horizon long ago. I suspect any
    kid or student looking at which programming language to learn would take
    one look at modern C++ and flee to Pythonville as fast as he could.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Wed Oct 9 07:22:50 2024
    On Wed, 9 Oct 2024 09:21:50 +0200
    Bonita Montero <[email protected]> boring babbled:
    Am 09.10.2024 um 09:15 schrieb [email protected]:

    I happen to think the removal of the need for decltype() would actually
    simplify things. ...

    It wouldn't make sense since a lambda is a pr-_value_ !

    Whooosh....

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)