Vitaliy, thank you for investigating that, and for reporting it to
Microsoft! In the meantime, we can implement the simple workaround Kenton
described. I will do so later this week, unless you beat me to it. :)

On Tue, Feb 28, 2017 at 4:10 AM, Vitaliy Bondarchuk <
[email protected]> wrote:

> i filled feedback form in the VS with this data and sent it to VS team.
> hope they will fix
>
> вторник, 28 февраля 2017 г., 13:23:34 UTC+2 пользователь Vitaliy
> Bondarchuk написал:
>
>> hi Kenton
>>
>> yes, when you initialize by explicit value (number or literal) - it works
>> better then when you initialize by return value of a function
>> look please here:
>>
>> header.h ==============
>> pragma once
>>
>> namespace test
>> {
>> typedef unsigned int uint;
>> typedef uint BitCount;
>>
>> template <typename T> inline constexpr T f1() { return T(0x12345678); }
>> constexpr BitCount v1 = f1<BitCount>();
>>
>> constexpr BitCount v2 = 0x12345678;
>>
>> inline constexpr unsigned int f3() { return 0x12345678; }
>> constexpr BitCount v3 = f3();
>>
>> constexpr auto v4 = "1234567890qwertyuiopasdfghjklzxcvbnm";
>>
>> inline constexpr auto f5() { return "1234567890qwertyuiopasdfghjklzxcvbnm";
>> }
>> constexpr auto v5 = f5();
>>
>> struct S
>> {
>> char a[4096];
>> };
>> inline constexpr auto f6() { return S(); }
>> constexpr auto v6 = f6();
>>
>> template <typename T> constexpr T f7 = { 1 };
>> constexpr BitCount v7 = f7<BitCount>;
>>
>> constexpr BitCount v9 = 0x12345678; //address of this is taken in the
>> main()
>> }
>> ====================================
>> ConsoleApplication1.cpp ==================
>> #include "stdafx.h"
>> #include "Header.h"
>> int main()
>> {
>> auto v10 = &test::v9;
>>
>> printf("1=%p\n", v10);
>>     return 0;
>> }
>> ====================================
>> Source.cpp ==================
>> #include "stdafx.h"
>> #include "Header.h"
>> ====================================
>> resulting map:
>>
>>
>> <https://lh3.googleusercontent.com/-pmJCKfJvUkg/WLVcr0774vI/AAAAAAAABrM/snp2E2sBU7AlprKABT0KY5XDOniKiNfiACLcB/s1600/Untitled.jpg>
>>
>> The compiler from VS version 14.0.25431.01 Update 3
>> Map analyzing tool http://www.sikorskiy.net/prj/amap/
>> The test project attached :)
>>
>>
>>
>>
>> понедельник, 27 февраля 2017 г., 23:10:04 UTC+2 пользователь Kenton Varda
>> написал:
>>>
>>> Oh wow, I didn't realize on my first read that the initialization
>>> expression makes a difference -- if it's just the value `1` rather than
>>> `kj::unit<T>()` then it gets elided properly? That's really strange! Since
>>> it is a constexpr, the compiler really ought to be evaluating and
>>> substituting the expression with the raw value at compile time, so that
>>> they are treated identically. I guess this is another symptom of MSVC's
>>> constexpr support being poor.
>>>
>>> But I guess this means there's an easy solution: Move the declarations
>>> of BITS, BYTES, etc. up into the #ifdef CAPNP_DEBUG_TYPES right above where
>>> they are declared currently. For the non-debug-types branch, initialize
>>> them all to `1` rather than `kj::unit<T>()`.
>>>
>>> Happy to accept such a PR.
>>>
>>> -Kenton
>>>
>>> On Mon, Feb 27, 2017 at 12:59 PM, Harris Hancock <[email protected]>
>>> wrote:
>>>
>>>> It does sound like a disappointing MSVC bug. Perhaps C++14 variable
>>>> templates generate better MSVC output? Something like:
>>>>
>>>> template <typename T> constexpr T unit {1};
>>>> constexpr BitCount BITS = unit<BitCount>;
>>>>
>>>> If so, that could be part of a solution. I'll test when I can.
>>>>
>>>> Harris
>>>>
>>>> On Mon, Feb 27, 2017 at 11:36 AM, Kenton Varda <[email protected]>
>>>> wrote:
>>>>
>>>>> Hi Vitaliy,
>>>>>
>>>>> Hmm, this seems like a pretty big bug in MSVC. It should be
>>>>> de-duplicating constants across object files, and it should be eliding the
>>>>> ones that aren't used.
>>>>>
>>>>> Note that these constants are only simple integers if you aren't
>>>>> defining CAPNP_DEBUG_TYPES. If CAPNP_DEBUG_TYPES is defined then these
>>>>> constants have special types that perform unit analysis, and your example
>>>>> code would not compile.
>>>>>
>>>>> I don't see how we can avoid defining the constants in a release
>>>>> build. They are used all over in the Cap'n Proto implementation. But it's
>>>>> very surprising to me that MSVC can't handle elide simple integer 
>>>>> constants.
>>>>>
>>>>> Harris, do you have any thoughts?
>>>>>
>>>>> -Kenton
>>>>>
>>>>> On Mon, Feb 27, 2017 at 3:07 AM, Vitaliy Bondarchuk <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> hi
>>>>>>
>>>>>> VS2015 (update pack 3) compiler produced own copy of these constants
>>>>>> in each object file:
>>>>>> constexpr BitCount BITS = kj::unit<BitCount>();
>>>>>> constexpr ByteCount BYTES = kj::unit<ByteCount>();
>>>>>> constexpr WordCount WORDS = kj::unit<WordCount>();
>>>>>> constexpr ElementCount ELEMENTS = kj::unit<ElementCount>();
>>>>>> constexpr WirePointerCount POINTERS = kj::unit<WirePointerCount>();
>>>>>>
>>>>>> As example map file of resulted binary tell me that I have 22 copies
>>>>>> of capnp::BITS in it. 88 bytes is not a big deal, but... it's a bit
>>>>>> inaccurate )
>>>>>> And this happens when the header visible to just 17 my cpp files. And
>>>>>> a cpp file doesn't need even use a constant - include the header enough 
>>>>>> for
>>>>>> produce variable in the object file.
>>>>>>
>>>>>> As I understand you use it for special types in DEBUG build.
>>>>>> But can it be a bit more trivial for RELEASE?
>>>>>>
>>>>>> I tried simple project with the header:
>>>>>>
>>>>>> namespace kj
>>>>>> {
>>>>>> template <typename T>
>>>>>> inline constexpr T unit() { return T(1); }
>>>>>>
>>>>>> inline constexpr unsigned int unit3() { return 1; }
>>>>>> }
>>>>>>
>>>>>> namespace capnp
>>>>>> {
>>>>>> typedef unsigned int uint;
>>>>>> typedef uint BitCount;
>>>>>>
>>>>>> constexpr BitCount BITS1 = kj::unit<BitCount>();
>>>>>> constexpr BitCount BITS2 = 1;
>>>>>> constexpr BitCount BITS3 = kj::unit3();
>>>>>> }
>>>>>>
>>>>>> all 3 constants have value 1. and all 3 properly can be used as size
>>>>>> of an array
>>>>>> #include "Header.h"
>>>>>>
>>>>>> void f();
>>>>>>
>>>>>> int main()
>>>>>> {
>>>>>> int b1[capnp::BITS1] = {};
>>>>>> int b2[capnp::BITS2] = {};
>>>>>> int b3[capnp::BITS3] = {};
>>>>>> f();
>>>>>>
>>>>>> printf("1=%d 2=%d 3=%d\n", capnp::BITS1, capnp::BITS2, capnp::BITS3);
>>>>>>
>>>>>>     return 0;
>>>>>> }
>>>>>>
>>>>>> but the map file is:
>>>>>> 3 .bss 62c 4 unsigned int const capnp::BITS1 ConsoleApplication1.obj
>>>>>> ?BITS1@capnp@@3IB
>>>>>> 3 .bss 630 4 unsigned int const capnp::BITS3 ConsoleApplication1.obj
>>>>>> ?BITS3@capnp@@3IB
>>>>>> 3 .bss 634 4 unsigned int const capnp::BITS1 Source.obj ?BITS1@capnp
>>>>>> @@3IB
>>>>>> 3 .bss 638 8 unsigned int const capnp::BITS3 Source.obj ?BITS1@capnp
>>>>>> @@3IB
>>>>>>
>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google
>>>>>> Groups "Cap'n Proto" group.
>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>> send an email to [email protected].
>>>>>> Visit this group at https://groups.google.com/group/capnproto.
>>>>>>
>>>>>
>>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Cap'n Proto" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>> Visit this group at https://groups.google.com/group/capnproto.
>>>>
>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.

Reply via email to