Attributes C++11 Attributes C++11 Attributes
Basic Syntax
[[attribute_name]] [[attribute_name(arguments…)]] [[attrib_namespace::attribute_name]] [[using attrib_namespace: attrib1, attrib2,…]] C++17
nodiscard
[[nodiscard("because...")]] ReturnType function () { … } auto x = function(); // function(); // COMPILER WARNING because... enum [[nodiscard]] E { a, b }; E make_E() { return E::a; } auto e = make_E(); // make_E(); // COMPILER WARNING class [[nodiscard]] C { … } C make_C() { return C{}; } auto c = make_C(); // make_C(); // COMPILER WARNING class A { [[nodiscard]] A (int) {…} … }; A a {1}; // A{0}; // COMPILER WARNING encourages compilers to issue warnings if (return) values are discarded
deprecated
[[deprecated]]
[[deprecated("why")]]
[[deprecated]] void old_function (); namespace [[deprecated]] v1 { … } using OldAlias [[deprecated]] = SomeType; enum [[deprecated]] Enumeration {}; enum E { enumerator [[deprecated]], enumerator2 [[deprecated]] = 7 }; struct S { [[deprecated]] Member m_; }; class [[deprecated("use D instead")]] C { … } template<typename T> class X; template<> class X<double> {}; template<> class [[deprecated]] X<float> {}; - indicates that an entity should no longer be used
- compilers usually issue warnings on usage
fallthrough
[[fallthrough]]
switch (expression) { case 1: handleA(); case 2: [[fallthrough]]; case 3: handleB(); default: handleC(); }; - indicates that fall through from a previous case label is intentional and should not be diagnosed
- can only be applied to a null statement
likely
if (…) { [[likely]] … } else { [[unlikely]] … } switch (…) { [[likely]] case 0: foo(); break; case 1: bar(); break; [[unlikely]] case 2: baz(); break; } allows compilers to optimize for cases where the path of execution that includes a statement or label marked [[likely]] / [[unlikely]] is more/less likely
maybe_unused
[[maybe_unused]]
[[maybe_unused]] void function (); using Alias [[maybe_unused]] = SomeType; enum [[maybe_unused]] Enumeration {}; enum E { enumerator [[maybe_unused]], enumerator2 [[maybe_unused]] = 7 }; struct S { [[maybe_unused]] Member m_; }; class [[maybe_unused]] C { … } suppresses compiler diagnostics about unused functions, types or enumerators
noreturn
[[noreturn]]
[[noreturn]] void always_throwing (…) { … // no return statement! if (…) throw Exception_Type1{}; … // no return statement! throw Exception_Type2{}; } // never reached! - specifies that a function never returns, i.e., it always throws an exception
- if
[[noreturn]]function actually returns ⇒ undefined behavior
no_unique_address
[[no_unique_address]]
struct EmptyType {}; struct S { Type member1_; [[no_unique_address]] EmptyType member2_ {}; }; - may be applied to non-static, non-bitfield members
- indicates that a member need not have an address that is distinct from all other non-static data members
- if a
[[no_unique_address]]member is non-empty any trailing padding may be reused to store other members
carries_dependency
[[carries_dependency]]
Allows compilers to omit memory fences in release-consume memory order if a dependency chain propagates in or out of a function:
void unknown_dependency (Type*); void propagates (Type* [[carries_dependency]]); std::atomic<Type*> atm; Type* p = atm.load(std::memory_order_consume); if (p) p->load(); // propagates if (p) unknown_dependency (p); // compiler might introduce memory fence // if function definition 'invisible' if (p) propagates (p); // compiler can omit memory fence! specify that a parameter carries a dependency into a function/lambda:
void function (Param [[carries_dependency]] p) { … } auto f = [](Param [[carries_dependency]] p) { … } specify that the return value carries a dependency out of the function:
[[carries_dependency]] ReturnType function (Param p) { … }
Comments…