--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
That's kind of too vague. What about "Use decltype only in places where you don't know the actual type of an object and where you'll need to do a redesign our CL to avoid use of decltype. Avoid it if it's possible to replace it with concrete type or the argument of template."This will automatically limit it to templates (if that't not a template then type is always known) and then only to templates which do "something unusual" - and these will probably attract attention of reviewer anyway.
On Thu, Sep 25, 2014 at 2:02 AM, Victor Khimenko <kh...@chromium.org> wrote:That's kind of too vague. What about "Use decltype only in places where you don't know the actual type of an object and where you'll need to do a redesign our CL to avoid use of decltype. Avoid it if it's possible to replace it with concrete type or the argument of template."This will automatically limit it to templates (if that't not a template then type is always known) and then only to templates which do "something unusual" - and these will probably attract attention of reviewer anyway.No, I explicitly don't want that level of strictness. It's often possible to avoid decltype by passing more type arguments to the template,
or by using template type arguments in more places within the template implementation.
The point of decltype is not just to make possible the exceptional cases where that's not true, it's to make other cases clearer and more readable. Sometimesdecltype(x) y = ...;is clearer thanT y = ...;...when it makes it apparent to the reader that "y has to match the type of x" and it's perhaps not instantly clear (maybe because your template takes multiple type arguments) what the type of x is, or your template didn't otherwise need to take T as a param.
Basically my POV is: decltype is a kludge and is hard to understand. But if use of it makes life easier in OTHER places (less arguments to templates, no need to redesign a large component, etc) then it's usually a net win. Less parametes in templates are always good if that does not limit expressiveness.But when you could just place something else in place of decltype without changes in other places then it's rarely a net win and even if it's a net win it's a minor one at best.
On Thu, Sep 25, 2014 at 5:47 PM, Stuart Morgan <stuart...@chromium.org> wrote:On Thu, Sep 25, 2014 at 2:36 AM, Victor Khimenko <kh...@chromium.org> wrote:Basically my POV is: decltype is a kludge and is hard to understand. But if use of it makes life easier in OTHER places (less arguments to templates, no need to redesign a large component, etc) then it's usually a net win. Less parametes in templates are always good if that does not limit expressiveness.But when you could just place something else in place of decltype without changes in other places then it's rarely a net win and even if it's a net win it's a minor one at best.Is this more true in Chromium than in Google code? Are Chromium engineers less capable than Google engineers of using it only when appropriate, or of pointing out 'bad' usage in review? If not one of these, why does Chromium need to deviate from Google's style guide here?Why are we having these discussions at all? Why not allow the same C++11 features which are allowed in Google's style guide?
The reasoning WRT auto and decltype is the same as with any other C++11 feature, but it's especially important for abuse-prone features like "auto" and "decltype": people must first learn to use them where impact is clearly positive then we could expand allowed scope and at some point restrictions could be removed altogether.Two years ago, when C++11 was first allowed in Google code, style guide contained pretty short list of whitelisted features. Later they have switched to blacklist and today that blacklist is pretty short. I guess Chromium is destined to repeat this path although we don't necessarily must repeat it exactly.
In Chrome OS we have switched most components to C++11 features long time ago, but we had to maintain GCC language extensions (using --std=gnu++11 instead of standard --std==c++11) simply because of one thing that comes from Chrome:HANDLE_EINTR() macro (https://code.google.com/p/chromium/codesearch#chromium/src/base/posix/eintr_wrapper.h&q=HANDLE_EINTR&sq=package:chromium&l=27&type=cs) which uses GCC's version of decltype() - typeof().
If decltype is allowed in Chrome code, not only will you make this nice language feature to be used by Chrome team, you will also save Chrome OS code base from non-standard language extension atrocities :)
$ cat test1.cc
int foo(int);
int bar(int x) {
return ({
typeof(x) result;
do {
result = foo(x);
} while (result != -1);
result; });
}
$ g++ -pedantic -c -std=c++11 test1.cc
test1.cc: In function 'int bar(int)':
test1.cc:4:10: warning: ISO C++ forbids braced-groups within expressions [-Wpedantic]
return ({
^
test1.cc:5:15: error: 'typeof' was not declared in this scope
typeof(x) result;
^
test1.cc:7:9: error: 'result' was not declared in this scope
result = foo(x);
^
test1.cc:8:16: error: 'result' was not declared in this scope
} while (result != -1);
^
$ cat test2.cc
int foo(int);
int bar(int x) {
return __extension__ ({
__typeof__(x) result;
do {
result = foo(x);
} while (result != -1);
result; });
}
$ g++ -pedantic -c -std=c++98 test2.cc
Note that Stuart and Peter have explicitly argued that this should be Chromium's position on the thread introducing C++11 support in Chromium (with the exception of differences that are mandated due to Chromium lacking library support at this time).
#define HANDLE_EINTR(x) ({ \ int eintr_wrapper_counter = 0; \ typeof(x) eintr_wrapper_result; \ do { \ eintr_wrapper_result = (x); \ } while (eintr_wrapper_result == -1 && errno == EINTR && \ eintr_wrapper_counter++ < 100); \ eintr_wrapper_result; \ })
template<typename Function, typename... Args> inline auto HANDLE_EINTR(Function fnc, Args... args) -> decltype(fnc(args...)) { using RetType = decltype(fnc(args...)); static_assert(helper::IsSignedInteger<RetType>::value, "Function must return a signed integer value"); RetType retval{}; int counter = 0; do { retval = fnc(args...); } while (retval < 0 && errno == EINTR && counter++ < 100); return retval; } |
template<typename Function, typename... Args> inline auto HANDLE_EINTR(Function fnc, Args&&... args) -> decltype(fnc(std::forward<Args>(args)...)) { using RetType = decltype(fnc(std::forward<Args>(args)...)); static_assert(helper::IsSignedInteger<RetType>::value, "Function must return a signed integer value"); RetType retval{}; int counter = 0; do { retval = fnc(std::forward<Args>(args)...); } while (retval < 0 && errno == EINTR && counter++ < 100); return retval; }
template <typename Lhs, typename Rhs = Lhs, ArithmeticPromotionCategory Promotion = (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) ? (MaxExponent<Lhs>::value > MaxExponent<int>::value ? LEFT_PROMOTION : DEFAULT_PROMOTION) : (MaxExponent<Rhs>::value > MaxExponent<int>::value ? RIGHT_PROMOTION : DEFAULT_PROMOTION) > struct ArithmeticPromotion; template <typename Lhs, typename Rhs> struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION> { typedef Lhs type; }; template <typename Lhs, typename Rhs> struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION> { typedef Rhs type; }; template <typename Lhs, typename Rhs> struct ArithmeticPromotion<Lhs, Rhs, DEFAULT_PROMOTION> { typedef int type; };