Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Captured functor requires parenthesis around it to be interpreted correctly. #1283

Open
feature-engineer opened this issue Sep 17, 2024 · 4 comments · May be fixed by #927
Open

[BUG] Captured functor requires parenthesis around it to be interpreted correctly. #1283

feature-engineer opened this issue Sep 17, 2024 · 4 comments · May be fixed by #927
Labels
bug Something isn't working

Comments

@feature-engineer
Copy link

feature-engineer commented Sep 17, 2024

Describe the bug
When using a functor inside a lambda, e.g.

std::array<std::string, 10> arr;
f: MyFunctor = ("Some initial value");
std::ranges::generate(arr, :() f&$*(););

This fails with some incomprehensible error saying is not invocable.
But std::ranges::generate(arr, :() (f&$*)();); works fine.

To Reproduce

Here's the code that fails (this is a toy example, ignore the bugs):

Letters: type = {
    str: std::string;
    i: size_t;
    operator=: (out this, str_: std::string) = {
        str = str_;
        i = 0;
    }
    operator(): (inout this) -> char = str[i++];
}

main: () = {
    arr: std::array<char, 10> = ();
    letters: Letters = ("This text would get copied letter by letter");
    std::ranges::generate(arr, :() letters&$*());
}

Here's the code that works:

Letters: type = {
    str: std::string;
    i: size_t;
    operator=: (out this, str_: std::string) = {
        str = str_;
        i = 0;
    }
    operator(): (inout this) -> char = str[i++];
}

main: () = {
    arr: std::array<char, 10> = ();
    letters: Letters = ("This text would get copied letter by letter");
    std::ranges::generate(arr, :() (letters&$*)());
}

I would have expected the first version to work, but failing that, I would have expected a better error message.

Here's the actual error message:

...: In lambda function:
...: error: expected primary-expression before ‘{’ token
  278 |     std::ranges::generate(arr, :() letters&$*());
      |                                                                                              ^
...: error: expected ‘;’ before ‘{’ token
  278 |     std::ranges::generate(arr, :() letters&$*());
      |                                                                                             ^ 
      |                                                                                             ;
...: In function ‘void fill()’:
...: error: no match for call to ‘(const std::ranges::__generate_fn) (std::array<char, 10>, fill()::<lambda()>)’
  278 |     std::ranges::generate(arr, :() letters&$*());
      |     ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~                                                   
In file included from /usr/include/c++/14.2.1/algorithm:63,
                 from /usr/include/cpp2util.h:257,
                 from /home/feature/projects/cpp2/ex1/build/_cppfront/main.cpp:6:
/usr/include/c++/14.2.1/bits/ranges_algo.h:947:7: note: candidate: ‘template<class _Out, class _Sent, class _Fp>  requires (input_or_output_iterator<_Out>) && (sentinel_for<_Sent, _Out>) && (copy_constructible<_Fp>) && ((invocable<_Fp&>) && (indirectly_writable<_Out, typename std::invoke_result<_Fp&>::type>)) constexpr _Out std::ranges::__generate_fn::operator()(_Out, _Sent, _Fp) const’
  947 |       operator()(_Out __first, _Sent __last, _Fp __gen) const
      |       ^~~~~~~~
/usr/include/c++/14.2.1/bits/ranges_algo.h:947:7: note:   candidate expects 3 arguments, 2 provided
/usr/include/c++/14.2.1/bits/ranges_algo.h:957:7: note: candidate: ‘template<class _Range, class _Fp>  requires (copy_constructible<_Fp>) && ((invocable<_Fp&>) && (output_range<_Range, typename std::invoke_result<_Fp&>::type>)) constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__generate_fn::operator()(_Range&&, _Fp) const’
  957 |       operator()(_Range&& __r, _Fp __gen) const
      |       ^~~~~~~~
/usr/include/c++/14.2.1/bits/ranges_algo.h:957:7: note:   template argument deduction/substitution failed:
/usr/include/c++/14.2.1/bits/ranges_algo.h:957:7: note: constraints not satisfied
In file included from /usr/include/c++/14.2.1/compare:40,
                 from /usr/include/c++/14.2.1/bits/stl_pair.h:65,
                 from /usr/include/c++/14.2.1/bits/stl_algobase.h:64,
                 from /usr/include/c++/14.2.1/algorithm:60:
/usr/include/c++/14.2.1/concepts: In substitution of ‘template<class _Range, class _Fp>  requires (copy_constructible<_Fp>) && ((invocable<_Fp&>) && (output_range<_Range, typename std::invoke_result<_Fp&>::type>)) constexpr std::ranges::borrowed_iterator_t<_Range> std::ranges::__generate_fn::operator()(_Range&&, _Fp) const [with _Range = std::array<char, 10>; _Fp = fill()::<lambda()>]’:
...:   required from here
  278 |     std::ranges::generate(arr, :() letters&$*());
      |     ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~                                                   
/usr/include/c++/14.2.1/concepts:360:13:   required for the satisfaction of ‘invocable<_Fp&>’ [with _Fp = fill::._anon_942]
/usr/include/c++/14.2.1/concepts:360:25: note: the expression ‘is_invocable_v<_Fn, _Args ...> [with _Fn = fill::._anon_942&; _Args = {}]’ evaluated to ‘false’
  360 |     concept invocable = is_invocable_v<_Fn, _Args...>;
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~


@feature-engineer feature-engineer added the bug Something isn't working label Sep 17, 2024
@JohelEGP
Copy link
Contributor

JohelEGP commented Oct 4, 2024

See also #748.

@JohelEGP
Copy link
Contributor

JohelEGP commented Oct 4, 2024

The bug is result of commit 94bea67
(modified by commit a18d22e).
I'll see if reverting it in #927 fixes the issue (it should!).

@JohelEGP JohelEGP linked a pull request Oct 4, 2024 that will close this issue
@JohelEGP
Copy link
Contributor

JohelEGP commented Oct 4, 2024

Done?
You still need the parentheses since commit 5663493,
otherwise it's parsed as a multiplication.

@JohelEGP
Copy link
Contributor

JohelEGP commented Oct 4, 2024

Note that commit 94bea67
made the rhs of the * lower to {}.
Operators don't accept a braced-init-list argument.
But commit 5663493 happened before,
which changed the * from dereference to multiplication.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants