8

I'm messing around with new C++20 lambdas, it seems I can declare a lambda taking a non type template param, but then I'm not able to call it.

#include <iostream>

int main() {

    // compiles fine
    auto f = []<bool ok>() { return ok; };

    // it even has an address??
    std::cout << &f;

    // f();    // error : no matching function for call to object of typ
    // f<true>(); // error : invalid operands to binary expression

    f.operator()<true>(); // compiles but somewhat... ugly
}

I looked at the relevant paper here but it doesn't seem to mention the calling syntax in such a case.

Is explicitly passing template arguments at the lambda call site forbidden? It would be a disappointing limitation, as I thought the intention was to make lambdas able to do as much as templates.

cigien
  • 57,834
  • 11
  • 73
  • 112
ThreeStarProgrammer57
  • 2,906
  • 2
  • 16
  • 24

1 Answers1

13

Is explicitly passing template arguments at the lambda call site forbidden?

No, but the issue is you're not specifying the template argument for the right entity. Note that f itself is not a template. It's an object of a non-templated type that contains a member operator() that is templated.

So when you do:

f<true>(); // error

you are specifying the template argument for f, but since f is not a template, you get an error.

On the other hand, as you've observed, this call:

f.operator()<true>();  // ok

is fine, because you are specifying the template argument for f's operator() which is indeed a template.

Also, this issue has nothing to do with non-type template parameters for lambdas, the same thing would happen if it were a type template parameter as well.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • 2
    If the lambda itself, i.e., the function object, cannot be parameterized, I wonder whether `f()` could have been defined by the standard as a kind of syntactic sugar for `f.operator()()`. – plexando Oct 24 '20 at 22:17
  • @plexando I can't see any reason that wouldn't work. However, it would be an additional rule for not much benefit I think. – cigien Oct 24 '20 at 22:45
  • 5
    @plexando: `f(1)` already means `(f1` when `f` is a value (not a template). – Davis Herring Oct 24 '20 at 22:54
  • @DavisHerring Well, that's that :) I didn't even think of that :) – cigien Oct 24 '20 at 22:56
  • @Davis Herring: :) Yeah right, Mr. (Red) Herring. And I always wondered who's behind this: [link](https://stackoverflow.com/questions/1642028/what-is-the-operator-in-c). – plexando Oct 24 '20 at 23:09
  • I wonder if it would be plausible to parse out `value< template arguments >()` and automatically convert to `value.operator()< template arguments >()`. It could be parsing hell. – Yakk - Adam Nevraumont Oct 26 '20 at 14:14
  • @Yakk-AdamNevraumont It's an interesting question. I can't think of a scenario where `value< args >()` could reasonably mean something else, but if it could, parsing unambiguously won't be possible :( – cigien Oct 26 '20 at 14:38
  • @cigien I'd be more worried about `value less than some complex expression greater than` prefix being parsed, then discarded when you hit `()`. Making the C++ parser even more complex would suck. – Yakk - Adam Nevraumont Oct 26 '20 at 14:57