auto a = b + c + d;std::vector<decltype(b + c)> vec;You can't. That's the entire purpose of the feature. If you are a library writer without previous explicit knowledge of that type, then it is completely non-observable whether you are dealing with a proxy or a non-proxy- in fact, you would never, ever deal with the proxy object, either implicitly or explicitly, because if a proxy was passed to your function, it would be automatically converted to a real_type.
The problem is fairly simple: It's too difficult to implement proxy objects in C++ right now.In C++11, I feel that, with type deduction, we should move away from concrete types and move to deal with only the interfaces they offer.The primary difficulty here comes when we deal with auto and decltype. These functions, whilst great, break any attempts we make to offer an interface-based substitute. Especially consider the case of expression templates- currently, they do not really work, as you cannot doauto a = b + c + d;
where the author of a has invoked expression templates to reduce complexity. Nor could you dostd::vector<decltype(b + c)> vec;
Thus, I propose an "automatic" operator. The automatic operator is invoked whenever type deduction is used, including decltype or auto, or whenever a requested member is not available. In addition, when overload resolution or template specialization is considered, an object which has an automatic operator is considered as the return type of that automatic operator, not as it's actual type, unless the actual type is specified directly and unambiguously with no intermediate conversions (except reference binding, cv qualifiers). The sample syntax I am showing is auto operator T(), which I consider to be the best choice, but it's a bit of a bikeshed issue as it's only used once at the point of definition and thus not especially significant.For now, I think it would be simplest to define that each type may only have one automatic operator, except that the operator may be overloaded by cv-qualifier or ref-qualifer- that is, any expression e involving any type T may automatically convert to one, and only one, type.For example, consider an expression template. Now, in our proxy objects, we can define an automatic conversion.class proxy {auto operator real_type() && { return evaluate(); }};
On Thursday, November 22, 2012 3:04:15 PM UTC-8, DeadMG wrote:The problem is fairly simple: It's too difficult to implement proxy objects in C++ right now.In C++11, I feel that, with type deduction, we should move away from concrete types and move to deal with only the interfaces they offer.The primary difficulty here comes when we deal with auto and decltype. These functions, whilst great, break any attempts we make to offer an interface-based substitute. Especially consider the case of expression templates- currently, they do not really work, as you cannot doauto a = b + c + d;
where the author of a has invoked expression templates to reduce complexity. Nor could you dostd::vector<decltype(b + c)> vec;
Thus, I propose an "automatic" operator. The automatic operator is invoked whenever type deduction is used, including decltype or auto, or whenever a requested member is not available. In addition, when overload resolution or template specialization is considered, an object which has an automatic operator is considered as the return type of that automatic operator, not as it's actual type, unless the actual type is specified directly and unambiguously with no intermediate conversions (except reference binding, cv qualifiers). The sample syntax I am showing is auto operator T(), which I consider to be the best choice, but it's a bit of a bikeshed issue as it's only used once at the point of definition and thus not especially significant.For now, I think it would be simplest to define that each type may only have one automatic operator, except that the operator may be overloaded by cv-qualifier or ref-qualifer- that is, any expression e involving any type T may automatically convert to one, and only one, type.For example, consider an expression template. Now, in our proxy objects, we can define an automatic conversion.class proxy {auto operator real_type() && { return evaluate(); }};
Why not `operator auto()`? Someone out there might actually have a `real_type`, so we can't keyword it. Plus, this is what it is, right? It's a conversion operator that is called when `proxy` is automatically type-deduced. It makes sense to use `auto` in that context.
Why not `operator auto()`? Someone out there might actually have a `real_type`, so we can't keyword it. Plus, this is what it is, right? It's a conversion operator that is called when `proxy` is automatically type-deduced. It makes sense to use `auto` in that context.
Why not `operator auto()`?
auto operator auto() {return DeduceTheTypeOfThis();}
auto operator auto() {return (std::string)(*this);}
auto operator auto() {return (value_type)(*this);}
auto operator std::string() {...}
auto operator int() {...}But, more importantly, you can only return deduced types. I don't personally have a problem with allowing automatic conversions to deduced types, but I do have a problem with not permitting non-deduced types.
If that's the only quibble you could think of, then I'm a happy man. In fact, you might well be right that it's a superior way of going about it. I simply thought that auto operator T() is more consistent with the semantics of what's going on, namely, that it's a conversion operator, and the auto specifies the conditions in which the conversion is valid- all the time- similar to explicit operator T() and implicit operator T().
auto operator std::string() {return {5};}
auto operator std::string() {return std::string{5};}
auto operator auto() {return std::string{5};}
auto operator std::string() { return decltype(*this){5}; }
auto operator std::string() { return decltype(*this){5}; }
;)
That would only work if `this` actually was `std::string`. This is an object which is meant to be converted into a std::string; it isn't part of it.
auto operator should also be picked for decltype, and since the declaration (auto operator std::string) is complete at that point, I don't see the problem.T operator auto() {}typedef T auto;auto delta = j - i; // the type of 'delta' is some expression template type
auto x = eval( delta + z ); // the type of 'x' is the final evaluated/reduced type.
this breaks the ability to use local type inference with intermediate values of expression templates where a user may not want the expression to be immediately evaluated at the point of construction but always will because the library writer has overridden the behavior of auto to do so.
one expression which could be quite complex and unreadable.
missing languages features that allow people to write efficient embedded domain-specific languages naturally in C++.
You're making some pretty core errors here.this breaks the ability to use local type inference with intermediate values of expression templates where a user may not want the expression to be immediately evaluated at the point of construction but always will because the library writer has overridden the behavior of auto to do so.If you know so much about my library that you want to do this when I have decided that it is not safe in general, then you can go and name the exact intermediate type for yourself. It's my library. I know whether or not I have references to temporaries in my code. You don't. If I don't have references to temporaries in my code then why would I override operator auto like this? It wouldn't make sense.
missing languages features that allow people to write efficient embedded domain-specific languages naturally in C++.You'd need some hardcore reflection to do better than expression templates.
On 10/13/13 1:40 AM, Xavi Gratal wrote:A user can still bypass that using a "universal reference," auto &&, which some might already find idiomatic.
I know it's been a while, but has this gotten anywhere near an actual
proposal?
I have a matrix library on the works where this could be extremely useful.
I'm currently having all my expression templates uncopiable and unmoveable
so that users can't get references to expired temporaries by using auto.
The member typedef auto does look cleaner to me. The differences I see are that
Also, the syntax
T operator auto() {}
looks good to me, but is it really necessary? It seems to do two things at
once: tell which type should be deduced by auto and how to convert to that
type. Why not just tell which type it should be converted to with something
like
typedef T auto;
and then the actual conversion would happen as usual, via a constructor in
T, or a separate operator T, which might be optionally declared as explicit.
Any thoughts? Anyone still interested in this?
- With two different functions, you have potentially different behaviors, which would generally be bad.
- If operator auto can be overloaded on const and reference qualification, that leads to divergent type deduction and behavior. Or, if it cannot, then the behavior is inconsistent with other conversion functions. (I haven't checked the proposal for this issue.)
Recently I suggested (on this board, no formal proposal) to forbid a type from being used to declare a named object. The mechanism is destructor overloading. A named object would be destroyed by an "lvalue" destructor.
https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/2tfKrgdKvfo
The behavior would be limited to a compile-time error such as a static_assert, not an automatic fix. As a library author, what do you think of that?
--
--- 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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
Did you look at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3748.pdf ?
- Some expressions might have completely different implementations depending on how they are combined. For example, in my matrix library, I use the syntax a.I() to represent the inverse of a matrix. Of course, to compute b*a.I(), there are better ways to do it than to compute the inverse and then multiply, so I only want to actually compute the inverse if it is not involved on a product, so I need an expression template until I know what happens to it. Then, if I do auto b=a.I(), I actually want to compute the inverse and b should be a matrix, not the expression template, which might contain references to temporaries.
It's just ugly to force users to use eval() constantly, and sometimes redundantly, because in many cases to know whether eval is necessary or not requires knowing too many about the implementation.
2013/10/13 Joel Falcou <joel....@gmail.com>
Did you look at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3748.pdf ?
Thanks for the link! I hadn't seen it.I especially like the using syntax, which is almost identical to the typedef I proposed, but it looks a bit more C++11.I don't think the explicit notation is necessary at all. I would propose that the overridden conversion works only for auto (and maybe const auto& and similar when they extend the lifetime of a temporary) but they don't apply to things like decltype(a+b) or even decltype(auto), making it easy to obtain the real type of the expression.Also, I don't think that they have to apply to template argument deduction (as suggested in section 5), because the main argument for this proposal is that it would prevent having dangling references to dead temporaries, and this wouldn't be a problem when passing the expression templates to other functions. Also, that would make the implementation of the library dealing with the expression templates much more cumbersome, since in there you actually want the deduced types to be the expression templates themselves.Finally, I don't share the compatibility concerns expressed in section 4, since it wouldn't change the meaning of any currently valid program.
So I believe that even if this functionality will only be used by implementors of a particular type of library, it will benefit all the users of these libraries, and it will isolate them from expression templates, which are just implementation details.
Il giorno domenica 13 ottobre 2013 17:34:33 UTC+2, Xavi Gratal ha scritto:So I believe that even if this functionality will only be used by implementors of a particular type of library, it will benefit all the users of these libraries, and it will isolate them from expression templates, which are just implementation details.
sorry for the intrusion, but
as a user of these libraries, I'd say that expression templates are not implementation details. I mean, <knowing> that some expression will be evaluated lazily, exploiting every possible bit of compile-time information available ( eventually extending the library on my own as well ), is the very reason I'd use such a library in the first place.
So, instead of hijacking the auto deduction rules, why not trying to make expression templates safer to use as non-temporaries instead ( a feature I'd find useful on its own BTW ) ?
For example, by marking a constructor as, say, "persist MyClass( ... )" then, given an initializing expression of an &&/const& reference R, temporaries of type MyClass ( whereever they appear ) could be automatically life-extended to the scope of R.
--
---
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.
I'd say there are two different things here. Whether an expression will be evaluated lazily is something the author should provide in the documentation and/or the description of the interfaces. How this is actually achieved internally, that's an implementation detail users should not care about, because the author should be able to change it in order to improve the library, as long as it doesn't modify the API (interface description included). If you want to modify the library, or extend it in ways that are not supported through the provided interfaces, that's perfectly ok, but that doesn't mean they are not implementation details, it means that you want to look at the implementation details.
Also, that should be an attribute of the reference, not the class, because sometimes you want to store references to types that are not even part of the library.
a=b; //a changed value!! that's certainly not what users of the library would expect
Finally, dangling references is not the only reason why someone would want to hide expression templates. Most expression templates, for example one that refers to a matrix product are supposed to be consumed only once, for efficiency reasons. If the user had a reference to an expression template, they could use it in several expressions, causing the same product to be computed multiple times.
Not to mention the issue of stuff like (a + b).c_str();.
I know it's been a while, but has this gotten anywhere near an actual proposal?