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