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…