auto and expression templates using attributes

75 views
Skip to first unread message

Till Heinzel

unread,
Oct 16, 2018, 4:44:22 AM10/16/18
to ISO C++ Standard - Future Proposals
I have previously worked a lot with expression templates, and using them together with auto is a pain - errors crop up all the time, and I ended up wrapping most of the functionality away.
I have been looking at P0672R0 and I think that sounds like a pretty good idea, but it also seems to be a quite invasive solution. I also looked at this discussion: a C++17 library solution to N4035, expression templates, auto and class template argument deduction, which does not seem to address the problem, as it is still up to the user to see when to use the proposed type.

So instead, I would propose adding a new attribute [[temporary_type]] that tells the compiler to emit a warning when an object of the type is used in a non-temporary context. I am not too certain on value categories, but I think it would work well if this would just mean a warning when the object is an lvalue. The user then knows to call some function, or to use a cast or an explicit type for the assignment, whatever works in the context of the library.
An accompanying attribute could be [[allowed_temporary_lvalue]], to suppress the warning at the call site. This would allow using the type warning-free within the library where it is created, and clearly express that this is a special case, not the primary use case for this type.

While I find P0672R0 interesting, I also think it may be overkill for a relatively niche problem. I ran into it using armadillo (linear algebra), the Wikipedia site specifies mostly linear algebra as a use case, and a quick google search ends up with the same thing. So on a value-effort graph, I think P0672R0 has to much effort for too little value. Attributes do not change the core language significantly, do not introduce new syntax or complexities, they simply tell compilers to emit warnings under certain conditions. That seems like a much cheaper way of getting some safety into the use of expression templates. It does not allow the drop-in replacement of expression templates, but I consider that a somewhat minor problem compared to the bugs that crop up when using them in an auto-riddled, modern-C++ world.

I am not an expert on the standard, so I would love some comments on this.

Arthur O'Dwyer

unread,
Oct 17, 2018, 11:08:35 AM10/17/18
to ISO C++ Standard - Future Proposals
(FWIW: A blog post I wrote back in July on the subject.)
I am surprised that P0672R0 does not have any R1 in the San Diego mailing.

(1) I like P0672's approach with `using auto = Matrix;`.

(2) I dislike P0672's cavalier suggestion that

    auto x = A*B;

should behave fundamentally differently from

    auto f = [](auto x){ ... }
    f(A*B);

in this respect. That kind of arbitrary subtlety is the bane of C++ and we don't need more of it.

(3) I am skeptical that either P0672 or Till's suggestion would solve the problem of

    std::vector<bool> vec(100);
    for (auto& elt : vec) {
        elt = true;
    }

which has been presented recently as a classic example of proxy types ruining everything for everybody.
But perhaps we don't need to solve that problem; we just need to teach everyone to use the correct

    std::vector<bool> vec(100);
    for (auto&& elt : vec) {
        elt = true;
    }

which Just Works for every type in the world, including proxy types and const vectors and even ranges that return rvalues from their iterators.

(4) Till, I think your idea is possibly fruitful, but you'd have to work out the corner cases — ideally by making a compiler implementation of the attribute (e.g. in Clang). What counts as an "lvalue"?  What happens in the "auto&& elt : vec" example above?  What happens if I just say "const auto& T = A*B;", even if I never use `T` as an lvalue?  What happens if I do that and then use `Matrix C = std::move(T);` — does that count as an lvalue use of `T`? And so on.  If you can get a Clang attribute with unit tests that look good, then it might help programmers even if P0672 never makes any more progress.

my $.02,
–Arthur

hubert.rein...@gmail.com

unread,
Oct 18, 2018, 11:12:43 PM10/18/18
to ISO C++ Standard - Future Proposals
I think there are a few operations that may be indicative of problem with delayed evaluation/proxy types:
copy/move
discard (I'll vaguely throw non-dependent operator void() out there)
reference binding

A temporary bound to a reference such that the reference extends the lifetime of the temporary is a potentially problematic case that you may want to consider with regards to the attributes you are proposing.
Reply all
Reply to author
Forward
0 new messages