hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] Cannot chain a member function call after constructing an object

bluetarpmedia opened this issue · comments

Describe the bug
Cannot chain a member function call on the same source code line after constructing an object.

To Reproduce
I'm trying to translate this C++ code:

using namespace std::chrono_literals;
std::thread([]{ std::this_thread::sleep_for(1000ms); }).detach();

into Cpp2:

using namespace std::chrono_literals;
_: std::thread = (:() = std::this_thread::sleep_for(1000ms);).detach();

But the detach call is invoked on the lambda instead of on the std::thread object.

std::thread auto_1 {CPP2_UFCS(detach)(([]() mutable -> void { std::this_thread::sleep_for(1000ms);  }))}; 

which leads to a C++ compiler error:

main.cpp2:6:25: error: no matching function for call to object of type '(lambda at main.cpp2:6:25)'
    6 |     std::thread auto_1 {CPP2_UFCS(detach)(([]() mutable -> void { std::this_thread::sleep_for(1000ms);  }))}; 
      |                         ^~~~~~~~~~~~~~~~~

Repro on Godbolt

This syntax does work:

std::thread(:() = std::this_thread::sleep_for(1000ms);).detach();

but I want to be explicit and use the _ wildcard.

Alternative syntaxes attempted

  1. This alternative syntax:
_:= std::thread(:() = std::this_thread::sleep_for(1000ms);).detach();

doesn't work because of the "anonymous name + type" rule:

error: an object can have an anonymous name or an anonymous type, but not both at the same type (rationale: if '_ := f();' were allowed to keep the returned object alive, that syntax would be dangerously close to '_ = f();' to discard the returned object, and such importantly opposite meanings deserve more than a one-character typo distance; and explicit discarding gets the nice syntax because it's likely more common)
  1. This syntax comes close but doesn't work either:
_: std::thread = std::thread(:() = std::this_thread::sleep_for(1000ms);).detach();

because it lowers to:

std::thread auto_1 {CPP2_UFCS(detach)(std::thread([]() mutable -> void { std::this_thread::sleep_for(1000ms);  }))}; 

which is effectively doing this:

std::thread auto_1 {
    std::thread([]() { }).detach()
};

Ah, I just realised my mistake, the syntax I was trying to write would be invalid, since I can't assign the result of detach to an anonymous object, and its type wouldn't be std::thread.