Const as const auto

411 views
Skip to first unread message

Carlos Licea

unread,
Mar 23, 2017, 3:07:17 PM3/23/17
to ISO C++ Standard - Future Proposals
So, I've jumped very hard into the auto bandwagon. So much so that most of my code now looks like:

auto foo = calculaeFoo();

It just makes it so much clearer, easier to refactor and less repetition.

However, I've found myself recanting from using const properly. I used to have my code const correct pretty much always:

const Foo foo = calculateFoo();

But now I just cannot be bothered. I know 

const auto foo = calculateFoo();

is not much longer but it just feels like cluttering the language again.

So I would like to float an idea: how about letting const imply const auto:

const foo = calculateFoo(); => const auto foo = calculateFoo(); => const Foo foo = calculateFoo();
const& foo = calculateFooReference(); => const auto& foo = calculateFooReference(); => const Foo& foo = calculateFooReference();

Would that work? surely I'm missing something but I wouldn't mind trying to iron the wrinkles myself if I have some guidance and there's interest.
 

Vishal Oza

unread,
Mar 23, 2017, 5:24:30 PM3/23/17
to ISO C++ Standard - Future Proposals
I think there is a proposal to remove auto from the type decalation but I have not heard to much recently. What about trying to moving const on right side of the equal operator? How would that affect the code?

Carlos Licea

unread,
Mar 23, 2017, 7:44:53 PM3/23/17
to ISO C++ Standard - Future Proposals


On Thursday, March 23, 2017 at 2:24:30 PM UTC-7, Vishal Oza wrote:
I think there is a proposal to remove auto from the type decalation but I have not heard to much recently. What about trying to moving const on right side of the equal operator? How would that affect the code?

that's an interesting proposal although not sure how much would the parser need to change to do that.

auto foo = const& calculateFooReference(); 

Jim Porter

unread,
Mar 23, 2017, 10:36:56 PM3/23/17
to std-pr...@isocpp.org
On 3/23/2017 6:44 PM, Carlos Licea wrote:
> that's an interesting proposal although not sure how much would the
> parser need to change to do that.
>
> auto foo = const& calculateFooReference();

One syntactic option would be to add a form of `const` that works like a
function call and just adds const-ness to the type of its expression,
like so:

auto foo = const(calculateFooReference());

I seem to recall a proposed feature that did something along these lines
except as a library, but I wouldn't mind seeing something like this as a
language feature.

- Jim

Nicol Bolas

unread,
Mar 23, 2017, 11:50:20 PM3/23/17
to ISO C++ Standard - Future Proposals

That's `std::as_const`. The main downside is that if you pass it a prvalue, it can't extend the lifetime of the temporary. Which of course is what the rvalue reference overload is deleted.

Arthur O'Dwyer

unread,
Mar 24, 2017, 5:21:25 PM3/24/17
to ISO C++ Standard - Future Proposals
That would 100% work, grammatically; I'm confident in that because it is exactly isomorphic to the old C-language rule known as "implicit int" (which was removed from C in 1999).  It used to be that

main() { }

meant "int main() { }", and

static const f = 42;

meant "static const int f = 42;".  C++ preserves vestiges of "implicit int" in the parsing of

static signed f = 42;

as a synonym for "static signed int f = 42;", but this special behavior of "signed" and "unsigned" are the only cases of "implicit int still kind of working" post-C89 as far as I know.

See https://herbsutter.com/2015/04/16/reader-qa-why-was-implicit-int-removed/ — notice particularly cartec69's comment, which seems to have anticipated your idea two years ago! ;)  In that blog post, Herb Sutter makes the point that if you allow implicit type names, you hamper the compiler's ability to diagnose typos. Consider

    // C++14 generic lambda
    auto f = [](const bar) { return bar(); };

Today, this unambiguously means "lambda taking one parameter of type 'const bar', unnamed, and returning a value-initialized object of type 'bar'; or, if 'bar' is not a type, diagnose an error."
After your proposed change, this means "either the above, or, if 'bar' is not a type, then this is a generic lambda taking one parameter of type 'const auto', named 'bar', and returning the result of applying operator() to that parameter."  Either interpretation is equally valid, so the compiler can't helpfully diagnose the problem if there was a problem.

We have ambiguous parses today too, of course; but it would be nice not to gratuitously add more of them.

As for solutions in C++17, have you tried-and-found-wanting all of the following syntaxes?
const auto foo = calculateFoo();
auto const foo = calculateFoo();
auto foo = std::as_const(calculateFoo());

–Arthur

T. C.

unread,
Mar 24, 2017, 5:59:23 PM3/24/17
to ISO C++ Standard - Future Proposals


On Friday, March 24, 2017 at 5:21:25 PM UTC-4, Arthur O'Dwyer wrote:
auto foo = std::as_const(calculateFoo());


 as_const doesn't do anything here. auto decays.

Nicol Bolas

unread,
Mar 24, 2017, 6:30:43 PM3/24/17
to ISO C++ Standard - Future Proposals

Also, you'll kill any hope of elision if `calculateFoo` returns a prvalue.

In any case, none of this seems really worth it just to remove 5 keystrokes.

Viacheslav Usov

unread,
Mar 25, 2017, 9:49:13 AM3/25/17
to ISO C++ Standard - Future Proposals
On Fri, Mar 24, 2017 at 10:21 PM, Arthur O'Dwyer <arthur....@gmail.com> wrote:

 
    // C++14 generic lambda
    auto f = [](const bar) { return bar(); };

Today, this unambiguously means "lambda taking one parameter of type 'const bar', unnamed, and returning a value-initialized object of type 'bar'; or, if 'bar' is not a type, diagnose an error."
After your proposed change, this means "either the above, or, if 'bar' is not a type, then this is a generic lambda taking one parameter of type 'const auto', named 'bar', and returning the result of applying operator() to that parameter."  Either interpretation is equally valid, so the compiler can't helpfully diagnose the problem if there was a problem.

This particular problem can be avoided by making const bar always mean unnamed constant of type bar when in a parameter declaration, thus always enforcing the current semantics.

Being able to define a constant type-deduced parameter would then be impossible with that syntax, so one would have to write const auto bar instead. I believe that is an acceptable tradeoff, because I do not think I see a very frequent use of constant parameters passed by value, as opposed to by reference. const &bar would mean a reference to a constant type-deduced object in every context, so this commonly used feature would not need to be compromised.

Also of note, here we have a certain overlap with various proposals of abbreviated generic lambda definitions. I think we will eventually have some of that adopted, which in my opinion is another argument in favour of enforcing the old semantics of const bar in parameter declarations.

Cheers,
V.

Nicol Bolas

unread,
Mar 25, 2017, 10:21:25 AM3/25/17
to ISO C++ Standard - Future Proposals
On Saturday, March 25, 2017 at 9:49:13 AM UTC-4, Viacheslav Usov wrote:
On Fri, Mar 24, 2017 at 10:21 PM, Arthur O'Dwyer <arthur....@gmail.com> wrote:

 
    // C++14 generic lambda
    auto f = [](const bar) { return bar(); };

Today, this unambiguously means "lambda taking one parameter of type 'const bar', unnamed, and returning a value-initialized object of type 'bar'; or, if 'bar' is not a type, diagnose an error."
After your proposed change, this means "either the above, or, if 'bar' is not a type, then this is a generic lambda taking one parameter of type 'const auto', named 'bar', and returning the result of applying operator() to that parameter."  Either interpretation is equally valid, so the compiler can't helpfully diagnose the problem if there was a problem.

This particular problem can be avoided by making const bar always mean unnamed constant of type bar when in a parameter declaration, thus always enforcing the current semantics.

Being able to define a constant type-deduced parameter would then be impossible with that syntax, so one would have to write const auto bar instead. I believe that is an acceptable tradeoff, because I do not think I see a very frequent use of constant parameters passed by value, as opposed to by reference. const &bar would mean a reference to a constant type-deduced object in every context, so this commonly used feature would not need to be compromised.

So what you're saying is that you want this:

auto foo = ...; //Deduces the type.
const bar = ...; //Deduces the type, but with `const`.
const &wee = ...; //Deduces the type, as a `const&`.
[](auto foo) {}; .//Deduces the type.
[](const bar) {}; .//Unnamed parameter of type `const bar`.
[](const &wee) {}; .//Deduces the type, as a `const&`.

We should not add such inconsistencies, all just to remove 5 characters from a line.

I'm not opposed to the idea that `&` and `&&` arguments can avoid the need for `auto`. But `const` alone should never be enough to induce type deduction.

Viacheslav Usov

unread,
Mar 25, 2017, 10:39:48 AM3/25/17
to ISO C++ Standard - Future Proposals
On Sat, Mar 25, 2017 at 3:21 PM, Nicol Bolas <jmck...@gmail.com> wrote:

> So what you're saying is that you want this:

Yes.

> We should not add such inconsistencies, all just to remove 5 characters from a line.

I see that differently. People being what they are, will save those keystrokes, making their code more vulnerable. That is a bigger issue than an inconsistency in a very rarely used case. And, as I said, I expect a better way of parameter type abbreviation anyway, which makes this whole point moot.

Cheers,
V.

Carlos Licea

unread,
Mar 26, 2017, 5:57:27 PM3/26/17
to ISO C++ Standard - Future Proposals
Certainly my poorly informed opinion is that you optimize for the common case while leaving enough room for the uncommon case. Your proposal looks to my a nice compromise.

Is there anything I can do to push forward this idea?

Peter Sommerlad

unread,
Mar 27, 2017, 1:48:37 AM3/27/17
to std-pr...@isocpp.org
Well

There are tools that will suggest adding const and will do so on the programmers behalf (www.cevelop.com). So the keystrokes can be saved without obfuscating the language even more. 

Sent from Peter Sommerlad's iPad
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAA7YVg2M83vNi_rH5fdCjUUp50OLnkPCWWZdWAYfTa4Ns26B7Q%40mail.gmail.com.

Viacheslav Usov

unread,
Mar 27, 2017, 5:02:58 AM3/27/17
to ISO C++ Standard - Future Proposals
On Mon, Mar 27, 2017 at 7:48 AM, Peter Sommerlad <peter.s...@hsr.ch> wrote:

> There are tools that will suggest adding const and will do so on the programmers behalf (www.cevelop.com). So the keystrokes can be saved without obfuscating the language even more. 

Advocating tools helping write proper C++ language as an argument against language obfuscation? At a minimum, I'd call that non sequitur.

Cheers,
V.

Viacheslav Usov

unread,
Mar 27, 2017, 6:39:28 AM3/27/17
to ISO C++ Standard - Future Proposals
On Sun, Mar 26, 2017 at 11:57 PM, Carlos Licea <car...@gmail.com> wrote:

> Is there anything I can do to push forward this idea?

This could be useful for you to read: https://isocpp.org/std/the-life-of-an-iso-proposal

Cheers,
V.

Carlos Licea

unread,
May 8, 2017, 1:37:49 AM5/8/17
to ISO C++ Standard - Future Proposals
Will do. Thanks.
Message has been deleted

Ray Hamel

unread,
May 8, 2017, 6:42:55 PM5/8/17
to ISO C++ Standard - Future Proposals
One obvious issue with the syntax suggested in the OP is it creates an ambiguous parse:

const foo(bar);

Does this declare a default-initialized variable bar of type const foo, or does it declare a variable foo of type const remove_reference<decltype(bar)>::type direct-initialized with bar ?
Message has been deleted

daniele...@gmail.com

unread,
May 9, 2017, 5:31:06 PM5/9/17
to ISO C++ Standard - Future Proposals

the refness& of the auto can already be put as one entity, so why not the constness? 

cauto? autoc? constauto? ca? car? (the last one for const auto&). then we can change auto to var and then we have var and car. 

Sorry I'll stop now. :)
 
Reply all
Reply to author
Forward
0 new messages