Doesn't constraining the "auto" in C++ defeat the purpose of it?
Solution 1:
A constraint on the deduced auto
type doesn't mean it needs to be a specific type, it means it needs to be one of a set of types that satisfy the constraint. Note that a constraint and a type are not the same thing, and they're not interchangeable.
e.g. a concept like std::integral constrains the deduced type to be an integral type, such as int
or long
, but not float
, or std::string
.
If I really need a
std::integral
datatype, couldn't I just omit theauto
completely?
In principle, I suppose you could, but this would at the minimum lead to parsing difficulties. e.g. in a declaration like
foo f = // ...
is foo
a type, or a constraint on the type?
Whereas in the current syntax, we have
foo auto f = // ...
and there's no doubt that foo
is a constraint on the type of f
.
Solution 2:
If I really need a
std::integral
datatype, couldn't I just omit the auto completely?
No, because std::integral
is not a type, it's a concept, a constraint on types (or if you will, a set of types rather than a single type).
Doesn't this defeat the purpose of auto here?
The original purpose of auto
in C++11 is telling the compiler: Whatever type you deduce.*
With C++20, auto
has an expanded use case - together with a concept, a constraint over types. auto
still tells the compiler: Whatever type you deduce - but the deduction must also respect the constraint.
* - ignoring issues like constness, l/rvalue reference etc.
Solution 3:
A concept often just move the error earlier in the compilation and makes code a bit more readable (since the concept name is a hint to the reader what you require from a type).
Rephrased:
It is rare you will ever use an auto variable in a way that it will work on every type.
For example:
auto fn(auto x) {
return x++;
}
will not work if you do:
f(std::string("hello"));
because you can not increment std::string
, the error is something like:
error: cannot increment value of type 'std::basic_string<char>'
return x++;
If you change the function to:
auto fn(std::integral auto x) {
return x++;
}
You will get an error like:
:6:6: note: candidate template ignored: constraints not satisfied [with x:auto = std::basic_string] auto fn(std::integral auto x) {
For a small example this, it does not matter a lot, but for real code often the fn would call fn2 that calls fn3... and you would get the error deep in the std/boost/... implementation file.
So in this way concepts move the error to the site of the first function call.