Reader Q&A: auto and expression templates

Motti asked:

While you’re dealing with reader’s Qs….

In your keynote in “Going Native” you mentioned that type inference should almost always be used, except for some obscure cases with expression templates.

Yes. To give people context, the idea is when declaring local variables, prefer to use auto to deduce the type. For example:

auto x = begin(v);

This seems like a rather serious wart on the language,

It’s a wart, but I don’t know about “serious” – it doesn’t come up that often. Still, your question is quite apropos:

part of the power of expression templates (to my understanding) is that they can be dropped in by a library implementer and thus improve the clients’ code without their knowledge.

Was there any discussion to allow type authors to opt-out of type inference? (e.g. by allowing an “operator auto()”). If this wasn’t discussed for C++11 is it being discussed for C++1y?

Yes, and even exactly that spelling has been suggested. I’ll take that as a +1 for discoverability if we name it that!

(For people reading this comment, if it doesn’t make any sense I wrote about it last year in my blog http://lanzkron.wordpress.com/2011/02/21/inferring-too-much/)

10 thoughts on “Reader Q&A: auto and expression templates

  1. I think that it would be better to have a mechanism where a class states what type should be deduced if *it* is auto-deduced. So if I have some string type that uses expression templates, I can force `auto str = string_type(…) + “foo”;` to be interpreted as `string_type str = string_type(…) + “foo”;`

  2. I personally think that using auto too often will reduce readability in the code. I would take it carefully.

  3. auto can (and will) indeed break C++03 expression templates, but with perfect-forwarding it’s now possible to write expression templates that properly ‘swallow’ temporaries such that they’re safe in the face of auto. I.e. in auto tree = a + std::string { “foo” } + c; the tree object would hold a reference to a, an std::string object with value “foo”, and a reference to c. This does mean that with something like auto more_tree = (std::string { “foo” } + a) + “bar”; there are moves (from the object with value “foo” in the temporary tree on the lhs of the last operator+ to the new object with value “foo” inside more_tree) where previously there were just some more references being created, which could be costly for a type where moves are effectively copies. But that’s somewhat premature, and the C++03 really was unsafe to begin with (the private type could already be accessed, and thus unsafely stored, through function template template).

  4. Why cant we gat those small things before 2017? I mean I know it is an ISO and all that, but tbh I dont get why you cant you just standardize “quickfixes” like every 2 y or something.

  5. @Motti: There is a difference between “opt-out of type inference” and “*change* the type inferred.” You asked for the former, and what I suggested was the latter.

    An `operator auto()` cannot return a type, since types in C++ are not things you can “compute” without template metaprogramming. If you want to change what type is inferred, then you need to have some kind of construct that resolves to an actual type.

  6. @Nicol Perhaps I gave the wrong impression when I said “opt out”, obviously you need a type for “auto” to deduce, my suggestion (as described in the post linked to above) was to have operator auto have a return type.

    e.g.

    string operator auto() const
    {
    return stringify();
    }

  7. Is there any reason why changing the definition of “operator string() const” to “operator string() &&”, would not work? Since that doesn’t seem to have been brought up, I’m guessing it’s for an obvious reason that I’ve just missed, aside from “most current compilers don’t support ‘rvalue references to *this’ “.

    It breaks type-deduction, which is unfortunate, but it seemingly prevents accidental undefined behavior, which is nice.

    Also, clang complains about “operator string() const &&” if the type of the object isn’t itself const, is that a defect in clang (or at least the random snapshot I happen to have)?

  8. I think it would be better to have something like ‘using auto = my_preferred_auto_type;’ instead of ‘my_preferred_auto_type operator auto();’ to avoid code duplication and to keep all the conversion operators look the same (as in, no return type specified). Although my first idea was also operator auto when I first encountered this problem, so from the discoverability point of view it is probably better :)

Comments are closed.