-
Notifications
You must be signed in to change notification settings - Fork 258
[BUG] Cpp2 types can't model std::assignable_from<SomeType>
#277
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
Sorry for the incoming rant |
Probably you can return |
I'm pretty sure Herb touches on this in https://www.youtube.com/embed/ELeZAKCN4tY. It's also most of the upper part of the roadmap. I have this representation of an integer. using value_type = std::uintmax_t;
using value_limits = std::numeric_limits<value_type>;
using vector_type = std::vector<value_type>;
const auto max_array_size = sizeof(vector_type) / sizeof(value_type);
using array_type = std::array<value_type, max_array_size>;
static_assert(max_array_size != 0);
export class integer;
struct integer_rep {
using value_type = waarudo::value_type;
bool is_negative_ : 1 = false;
bool is_vector_ : 1 = false;
std::size_t array_size : std::bit_width(max_array_size) = 0;
union {
array_type array{};
vector_type vector;
};
[[nodiscard]] constexpr integer_rep() noexcept { }
[[nodiscard]] constexpr integer_rep(const integer_rep&);
[[nodiscard]] constexpr integer_rep(integer_rep&&) noexcept;
constexpr ~integer_rep();
constexpr integer_rep& operator=(const integer_rep&);
constexpr integer_rep& operator=(integer_rep&&) noexcept;
// ...
}; The (copy, move) constructor and assignment pairs each reuse a common function that just depends on the input's rvalueness. template<class T> constexpr void integer_rep::copy_container(T&& r) noexcept(std::is_rvalue_reference_v<T&&>) {
if (is_vector()) std::construct_at(&vector, std::move(r.vector));
else std::construct_at(&array, r.array);
}
constexpr integer_rep::integer_rep(const integer_rep& r)
: is_negative_{r.is_negative()}, is_vector_{r.is_vector()}, array_size{r.array_size} {
copy_container(r);
}
constexpr integer_rep::integer_rep(integer_rep&& r) noexcept
: is_negative_{r.is_negative()}, is_vector_{r.is_vector()}, array_size{r.array_size} {
copy_container(std::move(r));
}
constexpr integer_rep::~integer_rep() {
if (const auto s = span(); not s.empty()) expects(s.back() != 0);
if (is_vector()) std::destroy_at(&vector);
}
template<class T> constexpr integer_rep& integer_rep::assign(T&& r) noexcept(std::is_rvalue_reference_v<T&&>) {
if (is_vector()) {
if (r.is_vector()) vector = std::move(r.vector);
else vector.assign(r.array.begin(), r.array.end());
} else {
if (r.is_array()) array = r.array;
else {
if (r.vector.capacity() == 0) array = {};
else {
std::destroy_at(&array);
std::construct_at(&vector, std::move(r.vector));
is_vector_ = true;
}
}
array_size = r.array_size;
}
is_negative_ = r.is_negative();
return *this;
}
constexpr integer_rep& integer_rep::operator=(const integer_rep& r) { return assign(r); }
constexpr integer_rep& integer_rep::operator=(integer_rep&& r) noexcept { return assign(std::move(r)); } C++'s |
@filipsajdak, Yes what you're showing here is exactly what I was talking about |
You probably mean @JohelEGP |
Oh, sorry for the mistake. |
What (to the best of your knowledge) would that end up looking like? |
I have had more time to think about it since I posted this. Perhaps this is one of the types that can't take advantage of Cpp2's single struct integer_rep {
bool is_negative_ = false;
boost::container::short_vector<value_type, max_array_size> vector; to contain the assignment's complexity in
|
Re the main question in this issue:
Good point, this will be fixed in the next commit. Generated Cpp1 assignment operators will Other questions:
Note that's not quite what Cpp2 is doing, and this will be clearer when you see the next commit... I'm writing this up as a design note. Also, note the generation is in the other direction -- in the upcoming next commit, Cpp2 generates the Cpp1 assignment operators from the constructor (generalized
You can still consume Cpp1 unions. You can also use the existing In the next commit you will be able to try writing the unified {copy,move} x {constructor,assignment}. You can still provide overloads if you want/need to write more specialized code for them. I finished the basic implementation last night and could push the commit now, but I think it wants to be committed with a doc page, so I'll write a doc page first today/tomorrow. Thanks! |
Will those be a preference over |
Metaclasses are an aid to write custom types. So you use a metaclass when you want a custom type of a certain kind. See paper P0707, section 3, for some examples of popular metaclasses. I hope to provide most of them in-the-box, including two different variations on Using enums as an example: My point of view here is not so much there's a whole lot wrong with built-in C enums or C++ enum classes (I'm a coauthor of the latter C++11 feature so I can't say much bad about it :) ), but if we don't have to make them be special-purpose language features hardwired into the compiler, and can write them as (metafunction) library code instead, then (a) it helps keep the language smaller and also (b) it enables people to write new powerful things (like flag-enums) as libraries without having to be a compiler developer. As for
Note that that "Note" comment is directly from the paper... ;) Also, note this proposal is older than |
See the wiki documentation page: https://github.com/hsutter/cppfront/wiki/Cpp2:-operator=,-this-&-that See also the new `pure2-types-smf*.cpp2` test cases for examples. Made Cpp1 assignment "return *this;", closes hsutter#277 Changed in<T> to pass fundamental types by value. Only those are known to be always complete. Partly addresses hsutter#270. Also partly improves hsutter#282.
Describe the bug
Cpp2 doesn't, by default, make generated
operator=
's return valuethis
and return type an lvalue to the type ofthis
.Doing this manually results in
cppfront
generating a Cpp1 constructor that returns*this
.To Reproduce
Steps to reproduce the behavior:
x.cpp2
:The generated constructor doesn't return
*this
.Additional context
I looked at 482bac8 and 4c52d2d. I found it unfortunate how no generated type of the latter was a model of
std::semiregular
by default, and generally ofstd::assignable_from<SomeType>
for the former, due to the generatedoperator=
's return type beingvoid
.The text was updated successfully, but these errors were encountered: