[cfe-dev] [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Thu Oct 12 08:52:23 PDT 2017


On 12 Oct 2017 01:22, "Eric Fiselier via cfe-dev" <cfe-dev at lists.llvm.org>
wrote:



On Wed, Oct 11, 2017 at 9:18 PM, David Jones <dlj at google.com> wrote:

> On Wed, Oct 11, 2017 at 6:11 PM, Eric Fiselier <eric at efcs.ca> wrote:
>
>>
>>
>> On Wed, Oct 11, 2017 at 6:30 PM, David Jones via cfe-dev <
>> cfe-dev at lists.llvm.org> wrote:
>>
>>> Hello,
>>>
>>> I'm currently working on migrating a large (100M+ LOC) C++ codebase to
>>> libc++. One particular pain point are the absence of constexpr constructors
>>> for std::pair, std::array, and std::tuple under C++11.
>>>
>>
>> Nit: std::array shouldn't have any constructors. But the other members
>> are conditionally constexpr.
>>
>>
>>> Some older versions of libstdc++ expose constexpr constructors under
>>> C++11, while libc++ does not; this causes build failures when using libc++.
>>>
>>
>> Hmm, just to clarify, it's not just older versions of libstdc++ that do
>> this, but newer ones as well. It's not like they removed it later.
>>
>>
>>>
>>> I would like to add a configuration variable that enables the constexpr
>>> qualifier on these constructors for C++11 or later, with the intent of
>>> advancing the C++ version as quickly as possible. Most of the uses can be
>>> trivially replaced by removing constexpr or switching to arrays, but this
>>> is churn for code which will (hopefully) soon be compliant anyhow.
>>>
>>
>> I'm actually quite sympathetic to enabling this extension by default,
>> since MSVC and libstdc++ both seem to. We're the odd man out.
>> If everybody else can safely get away with this, we should be able to as
>> well.
>>
>> BTW, by "C++11 or later" you mean "C++11" because they're already
>> required to be constexpr in C++14.
>>
>
> Naturally, yes... although what I really wanted to get at was "not C++03
> or earlier."
>
>
>>
>>
>>>
>>> I suspect this may be useful for other codebases that build in C++11
>>> mode to move to libc++... however, this would be a non-conforming
>>> extension. Adding a configuration option in __config_site.in (with the
>>> default being conforming behaviour) seems like it may be the most
>>> reasonable way to add the option.
>>>
>>
>> The extension is technically slightly worse than non-conforming; it's
>> explicitly forbidden. Implementations are not allowed to apply constexpr
>> where it isn't specified. However I think this rule should be relaxed to
>> allow implementations to backport newly added constexpr specifiers to older
>> dialects as an extension, as is this case.
>>
>> However my main concern with this as an on-by-default extension is that
>> it has the potential to break code. There are certain constexpr evaluations
>> that might result in a hard compile error that wouldn't before. I think
>> Clang has fixed most of these cases though.
>>
>>
> Right... I think on-by-default might be a bit too much.
>

Thankfully, despite my short-lived best efforts so far, I haven't been able
to construct a test case that I care about which breaks.
Admittedly, older Clang versions have problematic examples, but I suspect
very few people mix very old Clang versions
with brand new STL headers.

For example, the following code has silently different behavior across
dialects:

static std::pair<int, int> p(1, 2);

In C++14, the initialization of `p` occurs at compile time, but in C++11,
because the constructor is not constexpr,
the initialization happens at run time.


The initialization might happen at compile time, even in C++11 or C++98.
See http://eel.is/c++draft/basic.start.static#3

This bug also effects types composed using pair, Ex:

struct MyType {
template <class ...Args>
constexpr MyType(Args... args) : p(args...) {}
std::pair<int, int> x;
};

Such a type implicitly depends on `pair`s constructors to be constexpr in
order for
for instances of the class with static storage duration to be safely
constructed during
constant initialization.

IMHO, It's more important for libc++ to provide consistent and safe
semantics for `pair`
and `tuple` across dialects than it is to be pedantically correct. One
thing Howard Hinnent
taught me was to act in the best interest of your users; a pedantically
correct implementation
without users is of value to no one.

Therefore, I would rather adopt the extension universally, as everybody
else does, unless I
can come up with sensible examples of use-cases that break after
introducing the extension,

@Marshall, would you be supportive of this?


_______________________________________________
cfe-dev mailing list
cfe-dev at lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171012/f5a1ae43/attachment.html>


More information about the cfe-dev mailing list