Constexpr Everything Part 1: Constants #14487

pull DesWurstes wants to merge 1 commits into bitcoin:master from DesWurstes:patch-3 changing 32 files +184 −184
  1. DesWurstes commented at 2:10 PM on October 15, 2018: contributor

    I do this by hand, so make sure to report those whom I didn't see.

  2. achow101 commented at 5:30 PM on October 15, 2018: member

    Could you add some rationale as to why this is necessary? Code style changes need to significantly improve the developer experience and avoid serious programming bugs. I do not see how this change does either of those things, so NACK

  3. fanquake added the label Refactoring on Oct 15, 2018
  4. JeremyRubin commented at 12:19 AM on October 16, 2018: contributor

    Concept Ack -- making these constexpr allows us to add more static_asserts (and similar things) about relationships between constants.

  5. in src/zmq/zmqpublishnotifier.cpp:15 in e1791a639b outdated
      11 | @@ -12,10 +12,10 @@
      12 |  
      13 |  static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;
      14 |  
      15 | -static const char *MSG_HASHBLOCK = "hashblock";
      16 | -static const char *MSG_HASHTX    = "hashtx";
      17 | -static const char *MSG_RAWBLOCK  = "rawblock";
      18 | -static const char *MSG_RAWTX     = "rawtx";
      19 | +static constexpr char *MSG_HASHBLOCK = "hashblock";
    


    practicalswift commented at 7:09 AM on October 16, 2018:

    Starting with C++11 this conversion is no longer allowed (string literal to char *const).

    The intention was probably to make it static constexpr const char *MSG_HASHBLOCK or static constexpr const char MSG_HASHBLOCK[] ? :-)

    [cling]$ static const char * MSG_HASHBLOCK_0 = "hashblock"
    (const char *) "hashblock"
    [cling]$ static constexpr char *MSG_HASHBLOCK_1 = "hashblock"
    warning: ISO C++11 does not allow conversion from string literal to 'char *const' [-Wwritable-strings]
    (char *const) "hashblock"
    [cling]$ static constexpr const char *MSG_HASHBLOCK_2 = "hashblock"
    (const char *const) "hashblock"
    [cling]$ static constexpr const char MSG_HASHBLOCK_3[] = "hashblock"
    (const char [10]) "hashblock"
    

    Applies also to the three lines below.


    DesWurstes commented at 2:00 PM on October 16, 2018:

    Thirty minutes before I submitted this Pull Request, I submitted that pull request. Maybe I should add it to that one?


    practicalswift commented at 2:32 PM on October 16, 2018:

    @DesWurstes I think you might have misunderstood my comment.

    My point was that simply replacing const with constexpr for MSG_HASHBLOCK does not give the result you want to achieve in this case :-)

    More specifically you don't get a read-only string.

    What you have in master:

    [cling]$ static const char *MSG_HASHBLOCK = "hashblock";
    [cling]$ static_assert(MSG_HASHBLOCK[0] == 'h', "");
    error: static_assert expression is not an integral constant expression
    [cling]$ MSG_HASHBLOCK[0] = 'H';
    error: read-only variable is not assignable
    

    With your suggested change you get:

    [cling]$ static constexpr char *MSG_HASHBLOCK = "hashblock";
    warning: ISO C++11 does not allow conversion from string literal to 'char *const' [-Wwritable-strings]
    [cling] static_assert(MSG_HASHBLOCK[0] == 'h', "");
    [cling]$ MSG_HASHBLOCK[0] = 'H';
    Segmentation fault
    

    What I think you want:

    [cling]$ static constexpr const char *MSG_HASHBLOCK = "hashblock";
    [cling]$ static_assert(MSG_HASHBLOCK[0] == 'h', "");
    [cling]$ MSG_HASHBLOCK[0] = 'H';
    error: read-only variable is not assignable
    
  6. in src/validation.h:1 in e1791a639b outdated
       0 | @@ -1,4 +1,4 @@
       1 | -// Copyright (c) 2009-2010 Satoshi Nakamoto
       2 | +// Copyright (c) 2009-2010 Satoshi Nakamotoconstexpr
    


    practicalswift commented at 1:02 PM on October 16, 2018:

    I'm sure Satoshi loves constexpr – but this is taking it too far :-)

  7. practicalswift commented at 2:58 PM on October 16, 2018: contributor

    @JeremyRubin We can already use static_assert(…):s on the integer constants – we don't need constexpr for that :-)

    [cling]$ const int i = 0;
    [cling]$ static_assert(i == 0, "");
    [cling]$ int j = 0;
    [cling]$ static_assert(j == 0, "");
    error: static_assert expression is not an integral constant expression
    
  8. JeremyRubin commented at 11:09 PM on October 16, 2018: contributor

    @practicalswift I think that is compiler dependent?

    In any case, you also want to have relations be defined (e.g., constexpr functions).

  9. practicalswift commented at 6:25 AM on October 17, 2018: contributor

    @JeremyRubin

    Actually I think it follows directly from the C++11 standard that we can use static_assert(…):s on integer constants also in the absence of constexpr specifier:

    The syntax is ...

    static_assert(bool_constexpr, message)
    

    ... where bool_constexpr is contextually converted constant expression of type bool.

    What is a "contextually converted constant expression of type bool"?

    A constant expression is a literal constant expression, a reference constant expression, or an address constant expression.

    A converted constant expression of type T is an expression implicitly converted to type T, where the converted expression is a constant expression, and the implicit conversion sequence contains only:

    • constexpr user-defined conversions (so a class can be used where integral type is expected)
    • lvalue-to-rvalue conversions
    • integral promotions
    • non-narrowing integral conversions
    • And if any reference binding takes place, it is direct binding (not one that constructs a temporary object)

    A contextually converted constant expression of type bool is an expression, contextually converted to bool, where the converted expression is a constant expression and the conversion sequence contains only the conversions above. Such expressions can be used in noexcept specifications and static_assert declarations.

    The text above is taken from cppreference.

    FWIW, I tried compiling ...

    const int i = 0;
    static_assert(i == 0, "");
    

    ... in pedantic C++11 mode using clang, gcc, icc and MSVC. They all gladly accepted :-)

  10. fanquake commented at 2:49 AM on October 19, 2018: member

    @DesWurstes can you fix up the whitespace issues (and squash your fixup commits) so the tests will run

  11. DrahtBot added the label Needs rebase on Oct 20, 2018
  12. DrahtBot removed the label Needs rebase on Oct 20, 2018
  13. DrahtBot commented at 11:03 AM on October 20, 2018: member

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #14733 (P2P: Allow peer timeout to be configurable and speed up very slow test. by zallarak)
    • #14605 (Return of the Banman by dongcarl)
    • #14046 (net: Refactor message parsing (CNetMessage), adds flexibility by jonasschnelli)
    • #14035 (Utxoscriptindex by mgrychow)
    • #13972 (Remove 16 bits from versionbits signalling system by btcdrak)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  14. Constexprize constants a110fed3ab
  15. DesWurstes commented at 7:08 AM on November 16, 2018: contributor

    I understand that it is controversial to constexpr the constants as it's not a part of the code style. Should I open a separate Pull Request that replaces constexprs with consts?

  16. practicalswift commented at 7:54 AM on November 16, 2018: contributor

    @DesWurstes AFAIK there are no problems with constexpr from a code style perspective: I would say that we prefer contexpr:s for constants in new code. Have you gotten any contradicting information? :-)

    Regarding this PR I think any objections would be based on the code churn vs benefit trade-off.

  17. laanwj commented at 9:58 AM on November 23, 2018: member

    I would say that we prefer contexpr:s for constants in new code

    There's no mention of that. Before doing this, the developer notes need to be updated when to use constexpr and when const, along with the rationale. Not everyone is sufficiently up to date with C++11 to know this—is it always better to use constexpr? and if so, why does const still exist?

    The word constexpr doesn't appear in doc/developer-notes.md.

    Edit: and yes, code churn is the big factor here. We don't generally update the entire code base for changes in the code guidelines, this is only applied to new code, and only rarely—say, as cleanup before a release, done globally.

  18. MarcoFalke commented at 4:12 PM on November 28, 2018: member

    There hasn't been a follow-up to address the feedback (Document the new guideline in the developer notes), so I am closing this for now. Please let me know when you start working on this again, so I can reopen.

  19. MarcoFalke closed this on Nov 28, 2018

  20. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-21 21:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me