Skip to content

add_const_t VS plain const #7845

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

Open
frederick-vs-ja opened this issue Apr 19, 2025 · 12 comments · May be fixed by #7851
Open

add_const_t VS plain const #7845

frederick-vs-ja opened this issue Apr 19, 2025 · 12 comments · May be fixed by #7851

Comments

@frederick-vs-ja
Copy link
Contributor

The standard wording sometimes uses add_const_t and add_volatile_t when plain const and volatile are sufficient. IIUC the difference is that add_*_t block template argument deduction like type_identity_t, but we never use add_*_t in such contexts.

Would it be better to use plain const and volatile?

@Eisenwave

This comment has been minimized.

@Eisenwave
Copy link
Contributor

Seems like N1345 already discussed removing the std::add_ type traits because they're essentially pointless.

@jwakely compiled the discussion on the topic in 2013 here https://stackoverflow.com/a/16435566/5740428

For what it's worth, I can see the argument that std::add_const expresses intent a bit more clearly. On the other side, it is somewhat pointless. I think we should put something into our Specification Style Guidelines that definitively states whether

  • we should avoid std::add_const_T<T> and use const T instead whenever possible, or
  • use std::add_const_t when the intent is to add an extra const that was not previously there, like in std::as_const.

I feel like it's very difficult to come up with a proper objective guideline for when to use std::add_const_t over const T thought. There are only 15 occurrences of add_const_t in the whole document, but ten trillion occurrences of const T. What makes those handful of occurrences so special that they cannot just use const T like 99.99% of the document?

@AlisdairM
Copy link
Contributor

Historically, specifically C++03 era when the type traits were adopted for Library TR1, add_reference was essential as the reference collapsing rules were not adopted until C++11. and certainly compilers I have been using within the last few years still applied those rules in C++03 build modes --- although most compilers treat that as a DR.

The add_property traits also inhibit type deduction where they are used. I have not surveyed whether that effect is intentional design in the current library specification.

One thing to be wary of is that we need to be careful of the order of nesting with add_cv traits and add_reference traits --- that might be less of a concern if we were to use the simpler syntax directly, although I may be missing cases where we really want to emphasize that ordering.

One nagging doubt is that the traits provide the clarity of East Const, while the library is specified using Const West. Such concerns arise mostly in the context of add_pointer.

Final niggle is whether the interaction of add_cv and function and reference types is clearer to the less familiar reader --- or at least less likely to be misunderstood.

@Eisenwave
Copy link
Contributor

Eisenwave commented Apr 23, 2025

I'm fairly convinced that if you did

 template<class T>
-constexpr add_const_t<T>& as_const(T& t) noexcept;
+constexpr const T& as_const(T& t) noexcept;

... this would be clearer to the reader. It's not obvious whether std::add_const_t does anything special for certain types, or literally just adds const to the type (unless you have read its implementation). We add const to types all the time. For example, std::vector::push_back takes const T& and this combination of const and T works exactly as you would expect.

So overall, I think the unnecessary uses of the std::add_xxx traits in the library are detrimental to clarity. These trait uses feel like red herrings that mislead the reader into thinking that something more complicated is going on than there really is.

Historically, specifically C++03 era when the type traits were adopted for Library TR1, add_reference was essential as the reference collapsing rules were not adopted until C++11. and certainly compilers I have been using within the last few years still applied those rules in C++03 build modes --- although most compilers treat that as a DR.

That is an interesting insight. I'm not sure if you intend this to be an argument in favor of std::add_xxx traits. In any case, it's not really relevant to the present-day specification of the standard what the rationale was 10+ years ago. We've also moved on from typedef towards using, and should generally choose what's most clear.

The add_property traits also inhibit type deduction where they are used. I have not surveyed whether that effect is intentional design in the current library specification.

It doesn't matter in most cases regardless. Uses like in as_const aren't relevant to deduction. I'm not sure if any of the std::add_xxx uses in the standard have deduction impact.

Final niggle is whether the interaction of add_cv and function and reference types is clearer to the less familiar reader --- or at least less likely to be misunderstood.

I think that the interaction between reference types or functions and const is weird in general. It's not going to be any better for const or std::add_const.

@jwakely
Copy link
Member

jwakely commented Apr 23, 2025

I see no reason to continue using the traits rather than just const T.

@jensmaurer
Copy link
Member

Looks like we're sold here.

Pull request welcome to replace all uses of add_const with simply adding "const", throughout the standard library.

@AlisdairM
Copy link
Contributor

Last thought --- are we sure that this does not run afoul of the ABI concerns that killed https://wg21.link/P0181?

@jwakely
Copy link
Member

jwakely commented Apr 24, 2025

In general it could do, but I don't see a problem for any of the actual places that use add_const, as changed by #7851.

@jwakely
Copy link
Member

jwakely commented Apr 24, 2025

The concerns with https://wg21.link/p1715 are maybe more relevant. We could omit the std::as_const change if anybody's concerned about that.

@AlisdairM
Copy link
Contributor

My only concern is accidentally making a normative change believing it to be editorial.
I don't think I have any other concerns with the PR.

@frederick-vs-ja
Copy link
Contributor Author

frederick-vs-ja commented Apr 25, 2025

The concerns with https://wg21.link/p1715 are maybe more relevant. We could omit the std::as_const change if anybody's concerned about that.

Maybe off-topic: I find that all major implementations have some std::meow_t alias templates that are not defined to be equivalently to std::meow<...>::type as specified by the standard.

Lists

libc++:

libstdc++:

MSVC STL:

Given that ABI break is undesired, perhaps we should accept P1715 (with additional wording that touches compare_three_way_result_t and compare_three_way_result_t) as a DR.

@jensmaurer
Copy link
Member

I agree that P1715 is the right approach here (users of the standard library should simply not depend on ABI stability in this area), but until we get that, we should limit the editorial changes to those that are not at an ABI boundary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants