-
Notifications
You must be signed in to change notification settings - Fork 252
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
Add class template argument deduction (CTAD) for template user defined types (UDT) #369
Conversation
source/cppfront.cpp
Outdated
case passing_style::out : | ||
case passing_style::inout : arg_type += "&"; break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://godbolt.org/z/1dcWs4za1.
case passing_style::out : | |
case passing_style::inout : arg_type += "&"; break; | |
case passing_style::out : arg_type.insert(0, "cpp2::deferred_init<") += ">*"; break; | |
case passing_style::inout : arg_type += "&"; break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, thank you. It seems there is only a need to avoid cpp2::in<T>
as it is the only not deducible type. So, I guess I can make it simpler to reuse the cpp2 way of passing except for passing in
args.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One comment about data1 = (t = 42);
in the following code:
operator=: (out this, out t: T, inout y: Y, z: Z) = {
data1 = (t = 42);
data2 = y;
data3 = z;
}
I think we shall not support that kind of style of coding - there is very good alternative that works and is more clear about the intentions:
operator=: (out this, out t: T, inout y: Y, z: Z) = {
t = 42;
data1 = t;
data2 = y;
data3 = z;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did data1 = (t = 42);
work before? Now it errors with:
build/_cppfront/main.cpp:30:18: error: cannot initialize a member subobject of type 'int' with an rvalue of type 'void'
: data1{ t.construct(42) }
^~~~~~~~~~~~~~~
95688de
to
9721b18
Compare
f186f11
to
41f6749
Compare
Thanks! As I look at the examples, it strikes me that this should be (but isn't) falling into passing by It seems we should bypass
If we did those two things:
|
That's indeed a general improvement. Unfortunately, |
A way to support the deduction of an |
Currently after compiling the following code: ```cpp value: <T: type, Y: type, Z: type> type = { public data1: T; public data2: Y; public data3: Z; operator=: (out this, out t: T, inout y: Y, z: Z) = { t = 42; data1 = t; data2 = y; data3 = z; } operator=: (out this, t: * const T, y: *Y, move z: Z) = { data1 = t*; data2 = y*; data3 = z; } } main: () = { i : int; s := std::string("lvalue string"); v: value = (out i, s, :std::string = "temporary string"); std::cout << "(v.data1)$, (v.data2)$, (v.data3)$" << std::endl; s = "will be moved"; w: value = (v.data1&, v.data2&, move s); std::cout << "(w.data1)$, (w.data2)$, (w.data3)$" << std::endl; } ``` We will get the following error: ``` ../tests/ctad.cpp2... ok (all Cpp2, passes safety checks) ../tests/ctad.cpp2:22:11: error: no viable constructor or deduction guide for deduction of template arguments of 'value' value v {&i, s, std::string{"temporary string"}}; ^ ../tests/ctad.cpp2:12:13: note: candidate template ignored: couldn't infer template argument 'T' public: value(cpp2::in<T const*> t, cpp2::in<Y*> y, Z&& z); ^ ../tests/ctad.cpp2:6:13: note: candidate template ignored: could not match 'cpp2::out<T>' against 'cpp2::deferred_init<int> *' public: value(cpp2::out<T> t, Y& y, cpp2::in<Z> z); ^ ../tests/ctad.cpp2:1:52: note: candidate function template not viable: requires 1 argument, but 3 were provided template<typename T, typename Y, typename Z> class value { ^ 1 error generated. ``` After this change cppfront generates Class template argument deduction (CTAD) for template class that has constructors with the same argument type list as template arguments (order matters). cppfront will add the following cpp1 code to `Cpp2 type definitions and function declarations` section: ```cpp template<typename T, typename Y, typename Z> value(cpp2::deferred_init<T>*, Y&, Z const &) -> value<T, Y, Z>; template<typename T, typename Y, typename Z> value(T const* const &, Y* const &, Z&&) -> value<T, Y, Z>; ``` And will make the code compile and run successfuly: ``` 42, lvalue string, temporary string 42, lvalue string, will be moved ```
41f6749
to
955042b
Compare
I'm happy to try that... it creates an extra copy of the Pushed: e0125d7 |
Please, see #198 (comment). |
…ment thread 1. For a constructor parameter when `T` is a template parameter on the class, pass `T const&` for CTAD deduction. We do that already for all functions when `T` is a template parameter on the function, for general deduction. 2. For a parameter `* <anything>`, pass `<anything> *` by value (not `in<>`). We know it's a pointer, and should be passed by value.
OK, done... today's two commits (mentioned above) now apply all three changes discussed in this thread... quoting for convenience:
With these changes, the motivating example in this PR description now works, and Thanks again for the examples and discussion! Question: Even though the top example now works, I'm leaving this open for @filipsajdak to check and confirm... Filip, do these changes sufficiently address your motivation for this PR, so we should close it? Or are there additional examples that motivate the PR we should consider, and add those examples to this thread and rebase the PR? |
@JohelEGP Indeed, I've added a comment there asking you to please upgrade it to a whole new issue for argument-side qualifiers, so we don't lose this. I think we're getting to where we understand those well enough to enable more/all of them. Thanks for the reminder! |
I will check the examples tomorrow and will let you know. |
I have no other examples... I think we can close it. |
…sutter#369 comment thread
comment thread 1. For a constructor parameter when `T` is a template parameter on the class, pass `T const&` for CTAD deduction. We do that already for all functions when `T` is a template parameter on the function, for general deduction. 2. For a parameter `* <anything>`, pass `<anything> *` by value (not `in<>`). We know it's a pointer, and should be passed by value.
Currently, after compiling the following code:
We will get the following error:
After this change cppfront generates Class template argument deduction (CTAD) for template class that has constructors with the same argument type list as template arguments (order matters). cppfront will add the following cpp1 code to
Cpp2 type definitions and function declarations
section:And will make the code compile and run successfuly:
All regression tests pass.