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.
