In this post, you will learn how the compiler can help our code to run faster, and how it can generate some warnings in a single cross-compiler way.
On previous articles, we saw how to create constexpr functions which can evaluate at compile time, and how to communicate with the compiler using pragma directive. In this article, we’ll see how the compiler can help our code to run faster, and how it can generate some warnings in a single cross-compilers way.
Attributes
Attributes are the unified syntax for compiler extensions, such as the GNU and IBM language extensions __attribute__((…))
, Microsoft extension __declspec()
, etc.
Attributes can be used almost everywhere in the code, according to the action of the attribute. Some attributes have rules which force them to be in specific places and eliminate the option to place them in other ones.
Syntax
[[attribute-list]]
// comma separated list (Since C++11) [[using attribute-namespace : attribute-list]]
// all the attributes in this list belong to the same namespace. (Since C++17)
Today, there are four types of attributes:
[[identifier]]
– A simple attribute [[attribute-namespace::identifier]]
– An attribute with a namespace [[identifier(argument-list)]]
– An attribute with arguments [[attribute-namespace::identifier(argument-list)]]
– An attribute with both a namespace and an argument list
Standard Attributes
[[noreturn]] (C++11) | Indicates that the function does not return any value |
[[deprecated]] (C++14)
[[deprecated("reason")]] (C++14) | Indicates that the use of the name or entity declared with this attribute is allowed, but discouraged for some reason.
Usually deprecated features will be removed in future releases of an API. |
[[fallthrough]] (C++17) | Indicates that the fall through from the previous case label is intentional and should not be diagnosed by a compiler that warns on fall-through. |
[[nodiscard]] (C++17)
[[nodiscard("reason")]] (C++20) | Encourages the compiler to issue a warning if the return value is discarded. |
[[maybe_unused]] (C++17) | Suppresses compiler warnings on unused entities, if any |
[[likely]] (C++20)
[[unlikely]] (C++20) | Indicates that the compiler should optimize for the case where a path of execution through a statement is more or less likely than any other path of execution. |
cppreference – Attributes
For more standard attributes, see cppreference – attributes.
Examples
[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int f();
[[gnu::always_inline, gnu::const, gnu::hot, nodiscard]]
int f();
[[using gnu : const, always_inline, hot]] [[nodiscard]]
int f[[gnu::always_inline]]();
int f() { return 0; }
int main() {
int k [[maybe_unused]]; int num;
int res = 1;
std::cin >> num;
switch (num) {
case 0:
res++;
[[fallthrough]];
[[likely]] case 1: res++;
break;
[[unlikely]] case 2:
res--;
break;
}
std::cout << res << std::endl;
return EXIT_SUCCESS;
}
Compatibility between Compilers
To keep the compatibility between different compilers, unknown attributes will be ignored, and the compiler will warn about them. This way, when you compile the same code which uses a specific compiler attributes, using two different compilers, the code will compile in both of them, and the attribute will have the effect only on the one which supports it.