I just came across attributes enclosed in square brackets for the first time, and I've been doing a little background reading: http://en.cppreference.com/w/cpp/language/attributes.
For gcc at least, there seem to be multiple techniques allowed:
__attribute__((some_attribute))
and
[[some_attribute]]
Is this correct? When is one technique allowed or not allowed, preferred or not preferred? What's the difference?
It looks like [[some_attribute]] is allowed as of C++11 only, right?
According to N4659:
10.6.1 Attribute syntax and semantics [dcl.attr.grammar]
Attributes specify additional information for various source
constructs such as types, variables, names, blocks, or translation
units.
attribute-specifier-seq:
attribute-specifier-seqopt attribute-specifier
attribute-specifier:
[ [ attribute-using-prefixopt attribute-list ] ]
alignment-specifier
So, [[...]] is a standardized syntax.
In opposite, __attribute__ ((attribute-list)) is a syntax of gcc extension:
An attribute specifier is of the form __attribute__ ((attribute-list)). An attribute list is a possibly empty comma-separated sequence of attributes, where each attribute is one of the following:
...
As attributes were introduced in C++11 and you use gcc with C++11 support (or newer), then both types of syntax are available for you.
The [[foo]] syntax was introduced with C++11. But many compilers had their own syntax before that (which in some cases also supports some non-standardized attributes).
So in short: [[foo]] is standard and should work everywhere with a conforming compiler. The other syntaxes are compiler specific.
Related
I know that C++11-style attributes support vendor-specific attributes that are prefixed by a namespace. Both GCC and Clang support various attributes with the prefix either gnu:: (gcc and clang) or clang:: (clang only) which correspond to an equivalent __attribute__((...)) syntax.
The documentation for MSVC attributes shows that it supports the standard attributes, as well as a gsl:: attribute -- but it makes no mention of backwards-compatibility for __declspec attributes.
I'd expect something like __declspec(noinline) to have an attribute representation of [[msvc::noinline]] -- but I can't seem to find any documentation on this.
So my question is, does MSVC support __declspec as C++11-style attributes at all?
If it doesn't, would anyone happen to know they don't?
The original rationale for C++'s attributes was to abstract the various compiler-specific __attribute__ and __declspec features, so it would be weird if it's still not supported 9 years after standardization.
There is no [[msvc::noinline]] or other __declspec equivalents as of VC++ 2019.
From the official MSVC documentation for Attributes in C++:
In Visual C++, you can use the [[deprecated]] attribute instead of using declspec(deprecated) and the attribute will be recognized by any conforming compiler. For all other declspec parameters such as dllimport and dllexport, there is as yet no attribute equivalent so you must continue to use declspec syntax.
[ EDIT ] Information on why [[attributes]] are not more widely used in VC++, perhaps replacing __declspec entirely, is surprisingly scarce. The closest to an authoritative source that I found were these comments in the reddit thread C++ attribute specifier sequence, MSVC and me:
spongo2 - MSVC Dev Manager
We just had a rousing team room discussion on this topic. We definitely see the use case here and it's interesting but we're wondering if the fact that the number of places one can put attributes is large and growing would lead to surprising behavior.
STL - MSVC STL Dev
I would use [[msvc::kitty]] instead of __declspec(kitty) in the STL, in order to make our sources more palatable to other front-ends. I already switched to using [[noreturn]] instead of __declspec(noreturn) because that one's Standard.
My reading is that what's holding back a wider adoption is the concern about scopes of attributes vs. __declspec, and backwards compatibility in general.
According to Attributes in C++ the only __declspec() with an attribute replacement is [[deprecated]], for all other __declspec() modifiers you must continue to use __declspec.
Functional languages with pattern matching (sometimes?) have the possibility to ignore some bound values, but with C++17 structured bindings there seem to be no way to do that (std::ignore with structured bindings?). The advice is to use a dummy name, but then we'll get warnings about unused variables.
With the latest heads of both clang and gcc, this does the expected thing, which is nice and useful,
[[maybe_unused]] auto x =4 ; // fine, no warning
[[maybe_unused]] auto [a,dummyb,dummyc] = std::tuple<int,int,float>(1,1,1.0f);
but I would also have hoped this would work:
auto [g,[[maybe_unused]]dummyh,[[maybe_unused]]dymmyi] =
std::tuple<int,int,float>(1,1,1.0f);
is there a specific reason attributes can not be used here? (in the standard as well as technically). Neither gcc or clang accepts this.
Edit, collecting the support status: (thanks to godbolt/compiler explorer). It works as expected in (could be earlier also):
gcc 8.0 trunk (g++ 8.0.0 20171015 experimental)
clang 4.0.0
icc 18 (not tested, according to specs)
msvc 19.22 (probably earlier) (Fixed, according to bug report)
Try it out in godbolt at https://gcc.godbolt.org/z/H2duYd
In the structure bindings paper:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0144r2.pdf
they discuss their reasoning:
3.8 Should there be a way to explicitly ignore components?
The motivation would be to silence compiler warnings about unused names.
We think the answer should be “not yet.” This is not motivated by use
cases (silencing compiler warnings is a motivation, but it is not a
use case per se), and is best left until we can revisit this in the
context of a more general pattern matching proposal where this should
fall out as a special case.
Symmetry with std::tie would suggest using
something like a std::ignore:
tuple<T1,T2,T3> f();
auto [x, std::ignore, z] = f(); // NOT proposed: ignore second element
However, this feels awkward.
Anticipating pattern matching in the language
could suggest a wildcard like _ or *, but since we do not yet have
pattern matching it is premature to pick a syntax that we know will be
compatible. This is a pure extension that can wait to be considered
with pattern matching.
Although this does not explicitly address [[maybe_unused]], I assume the reasoning might be the same. Stopping compiler warnings is not a use-case.
As a resolution to CWG 2360, the working draft of the standard gained the following wording ([dcl.attr.unused]):
The attribute may be applied to the declaration of a class, a typedef-name, a variable (including a structured binding declaration), a non-static data member, a function, an enumeration, or an enumerator.
For an entity marked maybe_unused, implementations should not emit a warning that the entity or its structured bindings (if any) are used or unused. For a structured binding declaration not marked maybe_unused, implementations should not emit such a warning unless all of its structured bindings are unused.
Structured binding declarations were previously not explicitly mentioned.
Could C++ standards gurus please enlighten me:
Since which C++ standard version has this statement failed because (v) seems to be equivalent to (*&v)?
I.e. for example the code:
#define DEC(V) ( ((V)>0)? ((V)-=1) : 0 )
...{...
register int v=1;
int r = DEC(v) ;
...}...
This now produces warnings under -std=c++17 like:
cannot take address of register variable
left hand side of operand must be lvalue
Many C macros enclose ALL macro parameters in parentheses, of which the above is meant only to be a representative example.
The actual macros that produce warnings are for instance
the RTA_* macros in /usr/include/linux/rtnetlink.h.
Short of not using/redefining these macros in C++, is there any workaround?
If you look at the revision summary of the latest C++1z draft, you'd see this in [diff.cpp14.dcl.dcl]
[dcl.stc]
Change: Removal of register storage-class-specifier.
Rationale: Enable repurposing of deprecated keyword in future
revisions of this International Standard.
Effect on original feature: A valid C++ 2014 declaration utilizing the register
storage-class-specifier is ill-formed in this International Standard.
The specifier can simply be removed to retain the original meaning.
The warning may be due to that.
register is no longer a storage class specifier, you should remove it. Compilers may not be issuing the right error or warnings but your code should not have register to begin with
The following is a quote from the standard informing people about what they should do with regards to register in their code (relevant part emphasized), you probably have an old version of that file
C.1.6 Clause 10: declarations [diff.dcl]
Change: In C++, register is not a storage class specifier.
Rationale: The storage class specifier had no effect in C++.
Effect on original feature: Deletion of semantically well-defined feature.
Difficulty of converting: Syntactic transformation.
How widely used: Common.
Your worry is unwarranted since the file in question does not actually contain the register keyword:
grep "register" /usr/include/linux/rtnetlink.h
outputs nothing. Either way, you shouldn't be receiving the warning since:
System headers don't emit warnings by default, at least in GCC
It isn't wise to try to compile a file that belongs to a systems project like the linux kernel in C++ mode, as there may be subtle and nasty breaking changes
Just include the file normally or link the C code to your C++ binary. Report a bug if you really are getting a warning that should normally be suppressed to your compiler vendor.
Functional languages with pattern matching (sometimes?) have the possibility to ignore some bound values, but with C++17 structured bindings there seem to be no way to do that (std::ignore with structured bindings?). The advice is to use a dummy name, but then we'll get warnings about unused variables.
With the latest heads of both clang and gcc, this does the expected thing, which is nice and useful,
[[maybe_unused]] auto x =4 ; // fine, no warning
[[maybe_unused]] auto [a,dummyb,dummyc] = std::tuple<int,int,float>(1,1,1.0f);
but I would also have hoped this would work:
auto [g,[[maybe_unused]]dummyh,[[maybe_unused]]dymmyi] =
std::tuple<int,int,float>(1,1,1.0f);
is there a specific reason attributes can not be used here? (in the standard as well as technically). Neither gcc or clang accepts this.
Edit, collecting the support status: (thanks to godbolt/compiler explorer). It works as expected in (could be earlier also):
gcc 8.0 trunk (g++ 8.0.0 20171015 experimental)
clang 4.0.0
icc 18 (not tested, according to specs)
msvc 19.22 (probably earlier) (Fixed, according to bug report)
Try it out in godbolt at https://gcc.godbolt.org/z/H2duYd
In the structure bindings paper:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0144r2.pdf
they discuss their reasoning:
3.8 Should there be a way to explicitly ignore components?
The motivation would be to silence compiler warnings about unused names.
We think the answer should be “not yet.” This is not motivated by use
cases (silencing compiler warnings is a motivation, but it is not a
use case per se), and is best left until we can revisit this in the
context of a more general pattern matching proposal where this should
fall out as a special case.
Symmetry with std::tie would suggest using
something like a std::ignore:
tuple<T1,T2,T3> f();
auto [x, std::ignore, z] = f(); // NOT proposed: ignore second element
However, this feels awkward.
Anticipating pattern matching in the language
could suggest a wildcard like _ or *, but since we do not yet have
pattern matching it is premature to pick a syntax that we know will be
compatible. This is a pure extension that can wait to be considered
with pattern matching.
Although this does not explicitly address [[maybe_unused]], I assume the reasoning might be the same. Stopping compiler warnings is not a use-case.
As a resolution to CWG 2360, the working draft of the standard gained the following wording ([dcl.attr.unused]):
The attribute may be applied to the declaration of a class, a typedef-name, a variable (including a structured binding declaration), a non-static data member, a function, an enumeration, or an enumerator.
For an entity marked maybe_unused, implementations should not emit a warning that the entity or its structured bindings (if any) are used or unused. For a structured binding declaration not marked maybe_unused, implementations should not emit such a warning unless all of its structured bindings are unused.
Structured binding declarations were previously not explicitly mentioned.
Microsoft Visual C++ compiler has the property declaration construction
__declspec( property( get=get_func_name, put=put_func_name ) )
Is there a compiler independent version of Microsoft C++ __declspec(property(...)) or another analogs?
No.
As usual, an identifier preceded by __ is reserved to the compiler. In C++03 you have __cpluscplus (to identify C++ vs C), __FILE__ and __LINE__. All those are preprocessor entities.
In C++0x, the difference is blurred by the introduction of the __attribute__ word which is the first I know of that has semantics value, but it still does not do what you're looking for.
EDIT: Addressing #James spot on comment.
As Nicola Musatti says, there was a Borland proposal, primarily because Borland Delphi uses Properties heavily, and C++Builder (their C++ 'equivalent' to Delphi) therefore requires it.
In C++Builder, the code looks a bit like this.
__property __int64 Size = {read=GetSize, write=SetSize};
No. Similar mechanisms were proposed to the C++ standard committee but none was ever accepted (Here is one such proposal from Borland).
I've seen template based toy implementations, but they tend to be too inconvenient to be of practical use, the major problems being:
As nested class instances are not members of the enclosing class (as are Java inner class instances), you have to explicitly "connect" a property to its enclosing class, which makes declaration and initialization cumbersome.
There is no way to call function-like entities without parentheses, so you cannot invoke a custom-made property as if you were accessing a variable.