Skip to content

Conversation

@practicalswift
Copy link
Contributor

Rationale (from Bjarne Stroustrup's "C++11 FAQ"):

The enum classes ("new enums", "strong enums") address three problems with traditional C++ enumerations:

  • conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
  • conventional enums export their enumerators to the surrounding scope, causing name clashes.
  • the underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.

The new enums are "enum class" because they combine aspects of traditional enumerations (names values) with aspects of classes (scoped members and absence of conversions).

@practicalswift practicalswift force-pushed the scoped-enums branch 2 times, most recently from 6c9c5a7 to 4602120 Compare July 4, 2017 17:02

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using strongly typed enums causes RPCErrorCode to be static_casted too often. To gain strongly typed enums we loose readability.

Especially when considering that a more correct way to cast a strongly typed enum is static_cast<std::underlying_type<RPCErrorCode>::type>(RPCErrorCode::RPC_MISC_ERROR)
Which is even more unreadable.

Instead I suggest forgetting strong typing for this enum but still solve the scoping problem with:

class RPCErrorCode
{
public:
    enum
    {
    ...
    }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just make JSONRPCError accept a RPCErrorCode argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luke-jr Yes, that's my plan. I'll push those changes today hopefully :-)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luke-jr there would still be a few code == static_cast<int>(RPCErrorCode:: ...). But I agree it's not that many.

However changing JSONRPCError is kicking the can down to Pair where the conversion to int has to be done, or down to UniValue. It just seems to me like RPCErrorCode implicitly should be treated like an int since it will almost always be converted into one.

Copy link
Contributor Author

@practicalswift practicalswift Jul 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luke-jr @ArielLorenzo-Luaces Signature now changed:

-UniValue JSONRPCError(int code, const std::string& message)
+UniValue JSONRPCError(RPCErrorCode code, const std::string& message)

Only three static_cast<int>(RPCErrorCode) remain, and since they are explicit they should not cause any surprises (as opposed to implicit conversions).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think that RPCErrorCode and HTTPStatusCode are intrinsically different than the other enumerators, since they are sent over HTTP. They are also the only two that have explicit values assigned. They should be treated as integers always and they should require no conversion.

I would have suggested to hide conversion in encode/decode functions. Then the conversion would only have to be done once after receiving an http status. But then I see response.status >= 400 in bitcoin-cli.cpp. This suggests that HTTP status codes are not treated like enumerators and should not be compared to enumerators either.

RPCErrorCode and HTTPStatusCode should be treated more like macros instead.
Strong typing them would case unnecessary complexity due to the casting. But that would only be a problem if they begin to be used much more often, which is speculation on my part. So these changes are fine for now.

@practicalswift practicalswift force-pushed the scoped-enums branch 5 times, most recently from 25333b1 to 1840ee7 Compare July 6, 2017 21:32
@practicalswift practicalswift force-pushed the scoped-enums branch 2 times, most recently from e5a7dc6 to 5255dc7 Compare July 15, 2017 15:51
@practicalswift
Copy link
Contributor Author

Rebased!

@practicalswift practicalswift force-pushed the scoped-enums branch 3 times, most recently from cd78823 to 28cd41d Compare July 18, 2017 04:04
@practicalswift
Copy link
Contributor Author

Rebased again! :-)

@practicalswift practicalswift force-pushed the scoped-enums branch 6 times, most recently from 3091ec1 to e4dd710 Compare July 24, 2017 14:04
@practicalswift practicalswift force-pushed the scoped-enums branch 5 times, most recently from 040b561 to cd8b270 Compare August 1, 2017 07:57
@practicalswift
Copy link
Contributor Author

Rebased! :-)

@practicalswift practicalswift force-pushed the scoped-enums branch 2 times, most recently from 71ede09 to 1dcbb3c Compare August 3, 2017 12:38
@practicalswift
Copy link
Contributor Author

@laanwj Would it be possible to get a 0.17.0 milestone for this PR? :-)

@laanwj
Copy link
Member

laanwj commented Mar 27, 2018

Probably better to just merge this as there seems agreement to do it...
utACK 1f45e21

@laanwj laanwj merged commit 1f45e21 into bitcoin:master Mar 27, 2018
laanwj added a commit that referenced this pull request Mar 27, 2018
…ass")

1f45e21 scripted-diff: Convert 11 enums into scoped enums (C++11) (practicalswift)

Pull request description:

  Rationale (from Bjarne Stroustrup's ["C++11 FAQ"](http://www.stroustrup.com/C++11FAQ.html#enum)):

  >
  > The enum classes ("new enums", "strong enums") address three problems with traditional C++ enumerations:
  >
  > * conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer.
  > * conventional enums export their enumerators to the surrounding scope, causing name clashes.
  > * the underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.
  >
  > The new enums are "enum class" because they combine aspects of traditional enumerations (names values) with aspects of classes (scoped members and absence of conversions).

Tree-SHA512: 9656e1cf4c3cabd4378c7a38d0c2eaf79e4a54d204a3c5762330840e55ee7e141e188a3efb2b4daf0ef3110bbaff80d8b9253abf2a9b015cdc4d60b49ac2b914
laanwj added a commit that referenced this pull request Mar 27, 2018
…ons ("enum class")

0fee2b4 doc: Add note about our preference for scoped enumerations ("enum class") (practicalswift)

Pull request description:

  Add note about our preference for scoped enumerations (`enum class`).

  Context: #10742

Tree-SHA512: 0ab3465c2b734240cb38a05c2f6e75f1af54207a0f1a2e8115e7b367fd37e8966a2fc0240c6d4c2c66b6677b5f367eda4f4b783bbaa419777336c17f04adff06
jonasschnelli added a commit that referenced this pull request May 7, 2018
…with some compilers)

43f3dec Remove enum specifier (to avoid re-declare scoped enum as unscoped) (donaloconnor)

Pull request description:

  MSVC fails to compile with the changes made in #10742

  The problem is enum types were changed to scoped (`enum class`) but in some places `enum` as an unscoped is used.

  This is a very simple fix and I've tested it.

  Edit: Had to remove enum altogether - `enum class` doesn't compile on clang.

Tree-SHA512: 13e21666243585a133c74c81249a1fa4098d6b7aa3cda06be871fa017c0ad9bb7b0725f801160b9d31678448d668718197941fd84702ebdef15128c27d92cd70
PastaPastaPasta added a commit to PastaPastaPasta/dash that referenced this pull request Jun 12, 2020
…oin#10742)

-BEGIN VERIFY SCRIPT-

sed -i 's/enum DBErrors/enum class DBErrors/g' src/wallet/walletdb.h
git grep -l DB_ | xargs sed -i 's/DB_\(LOAD_OK\|CORRUPT\|NONCRITICAL_ERROR\|TOO_NEW\|LOAD_FAIL\|NEED_REWRITE\)/DBErrors::\1/g'
sed -i 's/^    DBErrors::/    /g' src/wallet/walletdb.h

sed -i 's/enum VerifyResult/enum class VerifyResult/g' src/wallet/db.h
sed -i 's/\(VERIFY_OK\|RECOVER_OK\|RECOVER_FAIL\)/VerifyResult::\1/g' src/wallet/db.cpp

sed -i 's/enum ThresholdState/enum class ThresholdState/g' src/versionbits.h
git grep -l THRESHOLD_ | xargs sed -i 's/THRESHOLD_\(DEFINED\|STARTED\|LOCKED_IN\|ACTIVE\|FAILED\)/ThresholdState::\1/g'
sed -i 's/^    ThresholdState::/    /g' src/versionbits.h

sed -i 's/enum SigVersion/enum class SigVersion/g' src/script/interpreter.h
git grep -l SIGVERSION_ | xargs sed -i 's/SIGVERSION_\(BASE\|WITNESS_V0\)/SigVersion::\1/g'
sed -i 's/^    SigVersion::/    /g' src/script/interpreter.h

sed -i 's/enum RetFormat {/enum class RetFormat {/g' src/rest.cpp
sed -i 's/RF_\(UNDEF\|BINARY\|HEX\|JSON\)/RetFormat::\1/g' src/rest.cpp
sed -i 's/^    RetFormat::/    /g' src/rest.cpp

sed -i 's/enum HelpMessageMode {/enum class HelpMessageMode {/g' src/init.h
git grep -l HMM_ | xargs sed -i 's/HMM_BITCOIN/HelpMessageMode::BITCOIN/g'
sed -i 's/^    HelpMessageMode::/    /g' src/init.h

sed -i 's/enum FeeEstimateHorizon/enum class FeeEstimateHorizon/g' src/policy/fees.h

sed -i 's/enum BlockSource {/enum class BlockSource {/g' src/qt/clientmodel.h
git grep -l BLOCK_SOURCE_ | xargs sed -i 's/BLOCK_SOURCE_\(NONE\|REINDEX\|DISK\|NETWORK\)/BlockSource::\1/g'
sed -i 's/^    BlockSource::/    /g' src/qt/clientmodel.h

sed -i 's/enum FlushStateMode {/enum class FlushStateMode {/g' src/validation.cpp
sed -i 's/FLUSH_STATE_\(NONE\|IF_NEEDED\|PERIODIC\|ALWAYS\)/FlushStateMode::\1/g' src/validation.cpp
sed -i 's/^    FlushStateMode::/    /g' src/validation.cpp

-END VERIFY SCRIPT-

Signed-off-by: pasta <pasta@dashboost.org>
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jun 12, 2020
…issues with some compilers)

43f3dec Remove enum specifier (to avoid re-declare scoped enum as unscoped) (donaloconnor)

Pull request description:

  MSVC fails to compile with the changes made in bitcoin#10742

  The problem is enum types were changed to scoped (`enum class`) but in some places `enum` as an unscoped is used.

  This is a very simple fix and I've tested it.

  Edit: Had to remove enum altogether - `enum class` doesn't compile on clang.

Tree-SHA512: 13e21666243585a133c74c81249a1fa4098d6b7aa3cda06be871fa017c0ad9bb7b0725f801160b9d31678448d668718197941fd84702ebdef15128c27d92cd70
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jul 17, 2020
…umerations ("enum class")

0fee2b4 doc: Add note about our preference for scoped enumerations ("enum class") (practicalswift)

Pull request description:

  Add note about our preference for scoped enumerations (`enum class`).

  Context: bitcoin#10742

Tree-SHA512: 0ab3465c2b734240cb38a05c2f6e75f1af54207a0f1a2e8115e7b367fd37e8966a2fc0240c6d4c2c66b6677b5f367eda4f4b783bbaa419777336c17f04adff06
@practicalswift practicalswift deleted the scoped-enums branch April 10, 2021 19:33
gades pushed a commit to cosanta/cosanta-core that referenced this pull request Feb 23, 2022
…oin#10742)

-BEGIN VERIFY SCRIPT-

sed -i 's/enum DBErrors/enum class DBErrors/g' src/wallet/walletdb.h
git grep -l DB_ | xargs sed -i 's/DB_\(LOAD_OK\|CORRUPT\|NONCRITICAL_ERROR\|TOO_NEW\|LOAD_FAIL\|NEED_REWRITE\)/DBErrors::\1/g'
sed -i 's/^    DBErrors::/    /g' src/wallet/walletdb.h

sed -i 's/enum VerifyResult/enum class VerifyResult/g' src/wallet/db.h
sed -i 's/\(VERIFY_OK\|RECOVER_OK\|RECOVER_FAIL\)/VerifyResult::\1/g' src/wallet/db.cpp

sed -i 's/enum ThresholdState/enum class ThresholdState/g' src/versionbits.h
git grep -l THRESHOLD_ | xargs sed -i 's/THRESHOLD_\(DEFINED\|STARTED\|LOCKED_IN\|ACTIVE\|FAILED\)/ThresholdState::\1/g'
sed -i 's/^    ThresholdState::/    /g' src/versionbits.h

sed -i 's/enum SigVersion/enum class SigVersion/g' src/script/interpreter.h
git grep -l SIGVERSION_ | xargs sed -i 's/SIGVERSION_\(BASE\|WITNESS_V0\)/SigVersion::\1/g'
sed -i 's/^    SigVersion::/    /g' src/script/interpreter.h

sed -i 's/enum RetFormat {/enum class RetFormat {/g' src/rest.cpp
sed -i 's/RF_\(UNDEF\|BINARY\|HEX\|JSON\)/RetFormat::\1/g' src/rest.cpp
sed -i 's/^    RetFormat::/    /g' src/rest.cpp

sed -i 's/enum HelpMessageMode {/enum class HelpMessageMode {/g' src/init.h
git grep -l HMM_ | xargs sed -i 's/HMM_BITCOIN/HelpMessageMode::BITCOIN/g'
sed -i 's/^    HelpMessageMode::/    /g' src/init.h

sed -i 's/enum FeeEstimateHorizon/enum class FeeEstimateHorizon/g' src/policy/fees.h

sed -i 's/enum BlockSource {/enum class BlockSource {/g' src/qt/clientmodel.h
git grep -l BLOCK_SOURCE_ | xargs sed -i 's/BLOCK_SOURCE_\(NONE\|REINDEX\|DISK\|NETWORK\)/BlockSource::\1/g'
sed -i 's/^    BlockSource::/    /g' src/qt/clientmodel.h

sed -i 's/enum FlushStateMode {/enum class FlushStateMode {/g' src/validation.cpp
sed -i 's/FLUSH_STATE_\(NONE\|IF_NEEDED\|PERIODIC\|ALWAYS\)/FlushStateMode::\1/g' src/validation.cpp
sed -i 's/^    FlushStateMode::/    /g' src/validation.cpp

-END VERIFY SCRIPT-

Signed-off-by: pasta <pasta@dashboost.org>
gades pushed a commit to cosanta/cosanta-core that referenced this pull request Mar 28, 2022
…issues with some compilers)

43f3dec Remove enum specifier (to avoid re-declare scoped enum as unscoped) (donaloconnor)

Pull request description:

  MSVC fails to compile with the changes made in bitcoin#10742

  The problem is enum types were changed to scoped (`enum class`) but in some places `enum` as an unscoped is used.

  This is a very simple fix and I've tested it.

  Edit: Had to remove enum altogether - `enum class` doesn't compile on clang.

Tree-SHA512: 13e21666243585a133c74c81249a1fa4098d6b7aa3cda06be871fa017c0ad9bb7b0725f801160b9d31678448d668718197941fd84702ebdef15128c27d92cd70
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.