Document number |
P3259R0 |
Date |
2024-05-09 |
Reply-to |
Jarrad J. Waterloo <descender76 at gmail dot com>
|
Audience |
Evolution Working Group (EWG) |
const by default
Table of contents
Abstract
Pure reference types with shallow const
semantics would benefit from allowing adding a const
modifier to a class definition in order to make them const
by default and hence more consistent with the behavior of lvalue references.
Motivational Examples
function_ref
given
template<class... S> class function_ref;
template<class R, class... ArgTypes>
class function_ref<R(ArgTypes...) cv noexcept(noex)> const
{
};
usage
void action(){}
void some_other_action()
{
function_ref<void ()> fr1{ action };
mutable function_ref<void ()> fr2{ action };
fr1 = function_ref<void ()>{ action };
fr2 = function_ref<void ()>{ action };
std::vector<function_ref<void ()>> v1{ fr1, fr2 };
std::vector<mutable function_ref<void ()>> v2{ fr1, fr2 };
}
optional
given
template <class T>
class optional<T&> const
{
};
usage
int i = 42;
optional<int&> oi1{ i };
optional<const int&> oi2{ i };
mutable optional<int&> oi3{ i };
mutable optional<const int&> oi4{ i };
oi1 = i;
oi2 = i;
oi3 = i;
oi4 = i;
std::vector<optional<const int&>> v1{ oi1, oi2, oi3, oi4 };
std::vector<mutable optional<const int&>> v2{ oi1, oi2, oi3, oi4 };
Motivation
Lvalue references are immutable. "A reference is similar to a const pointer such as int* const p (as opposed to a pointer to const such as const int* p)" References and constant pointers are easier to reason about dangling. Since references are not reseatable and constant pointers are not by default reseatable, they are just aliases to the referent that they point to. This means at compile time, once they point to a global, local or temporary, they always point to said global, local or temporary. Further since the constness is baked in, a programmer is less likely to forget to add it.
Making pure reference types with shallow const
semantics such as function_ref
and optional<&>
const by default
would make them more consistent with lvalue references. This will make them easier to use safely as it is easier to reason about the lifetimes of the referents that they point to.
More Potential Examples
class a const{};
class b mutable{};
class c const(true){};
class d const(false){};
class e mutable(true){};
class f mutable(false){};
While at a minimum, only adding const
to a class definition is needed, the other examples would be beneficial for completeness and to ease their usage in library definitions.
Should've, Could've, Would've
While not a part of this proposal, there are places in the standard library where types are implicitly const by default. For instance, adding the const by default class modifier to source_location
, initializer_list
, numeric_limits
, integer_sequence
, ration
and all of the type traits would not have negative consequences as all of its member access is currently const
only. It should also be noted that stacktrace_entry
, span
, mdspan
, locale
and all of the exceptions would also have been ideal candidates if it was not for their assignment operator. This is especially true of exeptions since they are usually thrown by value, catched by reference and rarely if ever reassigned mutably. The span
class would also have been ideal since it is a lightweight pure reference type like function_ref
and optional<&>
. The basic_string_view
is also in a similar situation of span
, if it wasn't for its assignment operator, remove_prefix
, remove_suffix
and swap
member functions. The last three member functions just as easily could have created a new basic_string_view
since it is a cheap stack type like span
.
References
Jarrad J. Waterloo <descender76 at gmail dot com>
const by default
Table of contents
Abstract
Pure reference types with shallow
const
semantics would benefit from allowing adding aconst
modifier to a class definition in order to make themconst
by default and hence more consistent with the behavior of lvalue references.Motivational Examples
function_ref
given
usage
optional
given
usage
Motivation
Lvalue references are immutable. "A reference is similar to a const pointer such as int* const p (as opposed to a pointer to const such as const int* p)" [1] References and constant pointers are easier to reason about dangling. Since references are not reseatable and constant pointers are not by default reseatable, they are just aliases to the referent that they point to. This means at compile time, once they point to a global, local or temporary, they always point to said global, local or temporary. Further since the constness is baked in, a programmer is less likely to forget to add it.
Making pure reference types with shallow
const
semantics such asfunction_ref
[2] andoptional<&>
[3]const by default
would make them more consistent with lvalue references. This will make them easier to use safely as it is easier to reason about the lifetimes of the referents that they point to.More Potential Examples
While at a minimum, only adding
const
to a class definition is needed, the other examples would be beneficial for completeness and to ease their usage in library definitions.Should've, Could've, Would've
While not a part of this proposal, there are places in the standard library where types are implicitly const by default. For instance, adding the const by default class modifier to
source_location
,initializer_list
,numeric_limits
,integer_sequence
,ration
and all of the type traits would not have negative consequences as all of its member access is currentlyconst
only. It should also be noted thatstacktrace_entry
,span
,mdspan
,locale
and all of the exceptions would also have been ideal candidates if it was not for their assignment operator. This is especially true of exeptions since they are usually thrown by value, catched by reference and rarely if ever reassigned mutably. Thespan
class would also have been ideal since it is a lightweight pure reference type likefunction_ref
andoptional<&>
. Thebasic_string_view
is also in a similar situation ofspan
, if it wasn't for its assignment operator,remove_prefix
,remove_suffix
andswap
member functions. The last three member functions just as easily could have created a newbasic_string_view
since it is a cheap stack type likespan
.References
https://isocpp.org/wiki/faq/references#reseating-refs ↩︎
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0792r14.html ↩︎
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2988r4.pdf ↩︎