From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13048 invoked by alias); 21 Oct 2011 13:55:05 -0000 Received: (qmail 13015 invoked by uid 22791); 21 Oct 2011 13:55:04 -0000 X-SWARE-Spam-Status: No, hits=2.1 required=5.0 tests=AWL,BAYES_50,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,MSGID_FROM_MTA_HEADER,RCVD_IN_DNSWL_NONE X-Spam-Check-By: sourceware.org Received: from blu0-omc3-s2.blu0.hotmail.com (HELO blu0-omc3-s2.blu0.hotmail.com) (65.55.116.77) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 21 Oct 2011 13:54:45 +0000 Received: from BLU0-SMTP383 ([65.55.116.73]) by blu0-omc3-s2.blu0.hotmail.com with Microsoft SMTPSVC(6.0.3790.4675); Fri, 21 Oct 2011 06:54:44 -0700 Message-ID: Received: from vbox162 ([79.192.244.118]) by BLU0-SMTP383.phx.gbl over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Fri, 21 Oct 2011 06:54:44 -0700 From: Andy Gibbs To: "Richard Guenther" CC: References: Subject: Re: [C++ Patch] __builtin_choose_expr *bump* Date: Fri, 21 Oct 2011 14:29:00 -0000 MIME-Version: 1.0 Content-Type: text/plain X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-10/txt/msg01980.txt.bz2 On Friday, October 21, 2011 12:04 PM, Richard Guenther wrote: > What's the motivation for this? Why can't it be implemented using C++ > features such as templates and specialization? Sorry for the delay in my reply. The motivation, simply put, is to be able to create both templates and macros that choose between two or more courses of action at compile time and do not generate code for the unchosen action(s), nor (importantly) cause compiler errors if the unchosen action(s) should be ill-formed. The end aim is in the generation of source code libraries for compile-time evaluation. An example in the template domain would be, having template specialisation without actually needing to specialise the template. Ordinarily, specialising a template requires a copy to be made and modified according to the specialisation. If the "base" template is changed, the specialisation also needs to be so adapted. Missing one specialisation in a long list leads to unpredictable problems (yes, there is bitter experience here!). If the majority of code is identical then it makes sense to try to either factor out the identical code and use some meta-template If struct or other such magic to limit the scope of the template specialisation. This can become brain-bending if not impossible if, for example, any of the relevant expressions cannot be parameters into a meta-template construct. It can also make the code very difficult to follow and debug. In these cases, __builtin_choose_expr can be beneficial to avoid the need to specialise, while keeping the clarity and breadth of the template's intended function. When it comes to macros, the use of __builtin_choose_expr can be very useful where one of the expressions would cause a compiler error. An example of such a macro is as follows: #define CONST(v) \ __builtin_choose_expr(util::can_use_const_wrapper::value, \ (util::const_wrapper::value) : \ ([&](){ constexpr auto o = (v); return o; })()) namespace util { template struct const_wrapper { static constexpr T value = t; }; template struct can_use_const_wrapper; /* code removed to keep example short! */ /* value = true for types that can be used in template value parameters */ } This is a part of a larger library of code for constexpr functions, a majority of which implement algorithms in such a way that the compiler can evaluate them but which if evaluated at run-time would have a huge performance hit (e.g. CRC calculation on a string). In this library, a second macro FORCE_CONSTEXPR is used to ensure these functions cannot be called at run-time or even inlined, but only evaluated at compile-time. The CONST macro is then used, among other things, to hint to the compiler that it needs to evaluate at compile-time. If __builtin_choose_expr in the CONST macro was replaced with "? :" then the code using it would fail to compile in certain situations, notably because C++ only permits certain types as template value parameters. However, it is not sufficient either to simply use the lambda expression alone since this fails with compiler errors in other situations. This is, I think, one example where it is not possible to use templates to get round the problem?... There is a further use of __builtin_choose_expr in this constexpr library, which is similar to its use in C, which is to enable a macro function to wrap and choose between a compile-time version of the algorithm and a run-time version of the algorithm, for example: #define CrcString(str) (__builtin_choose_expr(__builtin_constant_p(str), \ CONST(CrcString_compiler(str)), \ CrcString_runtime(str))) auto string = CrcString("test"); This might of course be implemented using "? :", but only if CrcString_compiler(...) and CrcString_runtime(...) return compatible types, which need not be so with __builtin_choose_expr. I hope this gives you some feeling for how __builtin_choose_expr may be used, or for that matter how I use it. I expect that others will find much more impressive uses! Thanks Andy