Constexpr members and narrowing

1,306 views
Skip to first unread message

Matthew Woehlke

unread,
Apr 5, 2019, 5:30:10 PM4/5/19
to std-dis...@isocpp.org
Is this code legal?

template <int X>
struct foo { constexpr static int bar = X; };

template <typename T>
void example()
{
auto x = size_t{ T::bar };
}

int main()
{
example<foo<3>>();
return 0;
}

GCC and clang think it is, but Visual Studio complains about a narrowing
conversion in `example`. Now, a *non*-constexpr `int` in that
initializer is definitely illegal, but an integer literal most certainly
*is* legal. This example is somewhere in between.

Alas, I am not one of those amazing people that know the standard
backwards and forwards, however a cursory search suggests that
expr.const¶12.3 may be relevant. (In particular, the footnote would seem
to indicate that VS is wrong, but I don't recall if footnotes are
normative, nor am I terribly confident I'm even reading the right thing...)

So... second opinions from some of you brilliant language lawyers?

(Hopefully this example is not overly simplified, but in case I messed
it up, the real code can be found at
https://github.com/Kitware/kwiver/blob/2f0f18f6b59e060777756fc5e00d71d003a27161/arrows/qt/tests/test_image.cxx#L451.)

--
Matthew

Andrew Tomazos

unread,
Apr 5, 2019, 10:17:34 PM4/5/19
to std-discussion
Isn't this the same as the following two lines:

    constexpr int bar = 3;
    size_t x{bar};

Does MSVC accept this? gcc does.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

Andrew Tomazos

unread,
Apr 5, 2019, 10:39:21 PM4/5/19
to std-discussion
The relevant part is [dcl.init.list]/7: "A narrowing conversion is an implicit conversion [snip] from an integer type [snip] to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral
promotions will fit into the target type."

So I think gcc is right and MSVC is wrong.

Matthew Woehlke

unread,
Apr 9, 2019, 11:51:10 AM4/9/19
to std-dis...@isocpp.org
On 05/04/2019 17.30, Matthew Woehlke wrote:
> Is this code legal?
> [snip old example]

Okay, I did a little more fiddling, and turns out my original example
wasn't quite right. Here is a corrected (and further simplified) example:

struct bar
{
bar(size_t a, size_t b) {}
};

int main()
{
constexpr int y = 5;

size_t works[] = { 1, y };
bar error{ 1, y };

return 0;
}

...does this change anyone's opinion?

--
Matthew

Brian Bi

unread,
Apr 9, 2019, 11:56:49 AM4/9/19
to std-dis...@isocpp.org
In this corrected example, which of the two list-initializations are you concerned about?

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.


--
Brian Bi

Matthew Woehlke

unread,
Apr 9, 2019, 11:57:23 AM4/9/19
to std-dis...@isocpp.org
Ah... and having realized what I missed in the original example, I found:

https://developercommunity.visualstudio.com/content/problem/246960/msconnect-3131094-narrowing-conversion-from-int-co.html

...so I guess MS agrees it's a bug :-).

--
Matthew

Matthew Woehlke

unread,
Apr 9, 2019, 12:32:03 PM4/9/19
to std-dis...@isocpp.org, Brian Bi
On 09/04/2019 11.56, Brian Bi wrote:
> On Tue, Apr 9, 2019 at 10:51 AM Matthew Woehlke wrote:
>> struct bar
>> {
>> bar(size_t a, size_t b) {}
>> };
>>
>> int main()
>> {
>> constexpr int y = 5;
>>
>> size_t works[] = { 1, y };
>> bar error{ 1, y };
>>
>> return 0;
>> }
>
> In this corrected example, which of the two list-initializations are you
> concerned about?

The second ("error") produces an error on VS, while the first ("works")
does not. (GCC/clang accept both.)

Realizing now that the problem is with *constructors*, I can see why
there *might* be a difference (overload resolution in particular adds a
wrinkle), hence the updated example. However, based on my own reading,
Andrew's replies, and the similar errors from both if I take away the
`constexpr`, I still believe this to be a VS bug... and apparently MS
agrees, as it is allegedly fixed in VS2019 (I don't have it to test).

--
Matthew
Reply all
Reply to author
Forward
0 new messages