Thanks to visit codestin.com
Credit goes to github.com

Skip to content

STL: Consider new conventions for preprocessor comments #351

@StephanTLavavej

Description

@StephanTLavavej

We have a long-standing convention of commenting all preprocessor directives. This is extremely useful when preprocessor-controlled code is large and/or nested, because the comments clearly identify region boundaries. (This is even more important now that clang-format indents all preprocessor directives at 0.) Here's an example with large regions:

STL/stl/inc/functional

Lines 1228 to 1250 in 1d39dfa

#if _HAS_STATIC_RTTI
_NODISCARD const type_info& target_type() const noexcept {
return this->_Target_type();
}
template <class _Fx>
_NODISCARD _Fx* target() noexcept {
return reinterpret_cast<_Fx*>(const_cast<void*>(this->_Target(typeid(_Fx))));
}
template <class _Fx>
_NODISCARD const _Fx* target() const noexcept {
return reinterpret_cast<const _Fx*>(this->_Target(typeid(_Fx)));
}
#else // _HAS_STATIC_RTTI
const type_info& target_type() const noexcept = delete; // requires static RTTI
template <class _Fx>
_Fx* target() noexcept = delete; // requires static RTTI
template <class _Fx>
const _Fx* target() const noexcept = delete; // requires static RTTI
#endif // _HAS_STATIC_RTTI

And nested regions:

STL/stl/inc/xstring

Lines 295 to 306 in 1d39dfa

#if _HAS_CXX17
#if _HAS_U8_INTRINSICS
if constexpr (is_same_v<_Elem, char8_t>) {
return __builtin_u8memcmp(_First1, _First2, _Count);
} else
#endif // _HAS_U8_INTRINSICS
{
return __builtin_memcmp(_First1, _First2, _Count);
}
#else // _HAS_CXX17
return _CSTD memcmp(_First1, _First2, _Count);
#endif // _HAS_CXX17

But when preprocessor-controlled code is small (down to a single line) and non-nested, it starts looking silly, as @SuperWig observed in #340 (comment) :

STL/stl/inc/functional

Lines 866 to 870 in 1d39dfa

#if _HAS_STATIC_RTTI
return typeid(_Callable);
#else // _HAS_STATIC_RTTI
return typeid(void);
#endif // _HAS_STATIC_RTTI

In newer code, we sometimes use "arrow comments" to make regions even more visible, which is an improvement for large and/or nested scenarios as usual:

STL/stl/inc/tuple

Lines 259 to 284 in 1d39dfa

#if _HAS_CONDITIONAL_EXPLICIT
template <class _This2 = _This,
enable_if_t<conjunction_v<is_default_constructible<_This2>, is_default_constructible<_Rest>...>, int> = 0>
constexpr explicit(
!conjunction_v<_Is_implicitly_default_constructible<_This2>, _Is_implicitly_default_constructible<_Rest>...>)
tuple() noexcept(conjunction_v<is_nothrow_default_constructible<_This2>,
is_nothrow_default_constructible<_Rest>...>) // strengthened
: _Mybase(), _Myfirst() {}
#else // ^^^ _HAS_CONDITIONAL_EXPLICIT ^^^ / vvv !_HAS_CONDITIONAL_EXPLICIT vvv
template <class _This2 = _This,
enable_if_t<conjunction_v<is_default_constructible<_This2>, is_default_constructible<_Rest>...,
_Is_implicitly_default_constructible<_This2>, _Is_implicitly_default_constructible<_Rest>...>,
int> = 0>
constexpr tuple() noexcept(conjunction_v<is_nothrow_default_constructible<_This2>,
is_nothrow_default_constructible<_Rest>...>) // strengthened
: _Mybase(), _Myfirst() {}
template <class _This2 = _This,
enable_if_t<conjunction_v<is_default_constructible<_This2>, is_default_constructible<_Rest>...,
negation<conjunction<_Is_implicitly_default_constructible<_This2>,
_Is_implicitly_default_constructible<_Rest>...>>>,
int> = 0>
constexpr explicit tuple() noexcept(conjunction_v<is_nothrow_default_constructible<_This2>,
is_nothrow_default_constructible<_Rest>...>) // strengthened
: _Mybase(), _Myfirst() {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

But similarly, it is generally silly for small non-nested scenarios (at least with simple conditions; the comments can be useful for complicated conditions even if the controlled code is small):

STL/stl/inc/vector

Lines 691 to 695 in 1d39dfa

#if _HAS_CXX17
return _Result;
#else // ^^^ _HAS_CXX17 ^^^ // vvv !_HAS_CXX17 vvv
(void) _Result;
#endif // _HAS_CXX17

We should consider developing a simple set of rules for contributors to follow. Example suggestion:

  • All #else and #endif directives should have arrow comments,
  • Except when the condition is simple, all of the controlled regions are a single line, and there is no nearby nesting.

That would require a bit of human judgement (what is "simple", what is "nearby"), but not very much.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationRelated to documentation or comments

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions