While qualifying an enumeration value with the name of the enumeration is not valid C++03, it is valid C++11, from what I understand. Despite this, MSVC 10 generates warning C4482 for the following:
enum E { A, B };
int i = E::A; // warning C4482 (but valid C++11?)
Since much of our code uses C++11 features (especially lambdas), it seems safe to disable this warning. Am I right that the code is valid C++11?
Note: I did not write the code in question, and I would prefer to not go through and change every occurrence of this.
Edit: Added some relevant links.
MSDN page for the warning.
Another question about the warning. The question and answers all seem to reference C++03.
Since much of our code uses C++11 features (especially lambdas), it seems safe to disable this warning.
If you're already relying on C++11 features, then yes. C++11 does allow you to use regular enums scoped by the enumeration's name. Microsoft had this as an extension for some time, so they issued a warning about the non-standard behavior.
So you can disable it.
Note that older compilers like VC2010, instead of warning, did raise compile error C2653 (with message "... is not a class or namespace name").
Related
I have a function I will need to leave partially implemented for a variety of reasons and I want to prevent future users (read as me in the future when I have forgotten that I did this) to know the function is incomplete, buggy and untested.
Option n1 is merely adding a comment // Warning this thing is partially implemented and will break randomly
This however won't create compile time warnings so, I am not a fan.
Option n2 is to use [[deprecated("reason")]] which has the advantage of raising compile warnings but its misleading, the function wasn't deprecated it's actually the opposite of deprecation, it's a WIP and will perhaps one day be fully implemented.
Are there alternatives?
The [[deprecated]] attribute is exactly what this is for (emphasis mine) :
https://en.cppreference.com/w/cpp/language/attributes
[deprecated]
[deprecated("reason")]
indicates that the use of the name or entity declared with this attribute is allowed, but discouraged for some reason
You can still use the function, you just get a warning message that you shouldn't rely on its use.
Caveat: MSVC breaks the standard and emits a compiler error (due to SDL flag being turned on by default) instead of a warning.
The only thing in standard C++ for this is the [[deprecated("message")]] attribute.
GNU has a non-standard Function Attribute for warning messages:
warning ("message")
If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, a warning which will include message will be diagnosed. This is useful for compile time checking, especially together with __builtin_constant_p and inline functions. While it is possible to define the function with a message in .gnu.warning* section, when using this attribute the problem will be diagnosed earlier and with exact location of the call even in presence of inline functions or when not emitting debugging information.
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.
Was std::string.npos ever valid? (As opposed to the correct std::string::npos.)
I am seeing it a lot in an old project I'm working on, and it does not compile with VS2010.
Is it something from the pre-standard days?
The C with classes syntax for naming a class member was, in fact, a dot:
class X {
public:
void f();
};
void X.f() // a dot! see D&E 2.3
{
}
However, the :: syntax had not yet been invented. The std namespace didn't exist yet either. Thus the std::string.npos wasn't ever valid as either C with classes or standard C++.
I suspect std::string.npos is purely Microsoft's extension (or a bug?). It might be inspired by the old syntax, and might be not.
No, std::string.npos was never valid, and no, it's not something from the pre-standard days.
I see other answers mentioning that MSVC has allowed that notation.
However, MSVC is not a very compliant compiler. For example, it lets you freely bind a temporary to a reference to non-const. For another example, for Windows GUI subsystem applications you have to use not well-documented switches to make it accept a standard main. Much has improved since Microsoft hired Herb Sutter (and other guy that I don't remember the name of right now) to fix up their monstrous compiler. And in relative terms it has been really great, but in absolute terms, well that compiler is still a bit lacking.
Access to any static member via class name and dot was unfortunately allowed by prior versions of MSVC.
#include <iostream>
struct A
{
static int a;
};
int A::a;
int main()
{
std::cout << A.a;
}
This code is happily accepted by MSVC9.0 with a warning
Warning 1 warning C4832: token '.' is
illegal after UDT 'A'
The C++ standard obviously disallows access to a static member via className.memberName (although it is perfectly legal to access a static member via an object object.staticMemberName).
My common sense tells me that if MSVC is aware that this is not standard and gives a warning, then we can turn that extension off. We go to Project Propertied -> C/C++ -> Language and set Disable Language Extensions to Yes. Do you think anything changes? Of course not, the compiler still accepts the illegal code with the same warning. I sometimes wonder what Disable Language Extensions actually does...
I'm compiling some c++ code in MinGW GCC 4.4.0, and getting warnings with the following form...
warning: invalid access to non-static data member '<membername>' of NULL object
warning: (perhaps the 'offsetof' macro was used incorrectly)
This problem seems familiar - something I've tried to resolve before and failed, I think, but a while ago. The code builds fine in Visual C++, but I haven't built this particular code recently in any other compiler.
The problem code is the following template...
template<typename T>
class c_Align_Of
{
private:
struct c_Test
{
char m_Char;
T m_Test;
};
public:
enum { e_Align = offsetof (c_Test, m_Test) };
};
Obviously I can probably use some conditional compilation to use compiler-specific functions for this, and I believe C++0x will (at long last) make it redundant. But in any case, I cannot see anything wrong with this use of offsetof.
Very pedantically, it's possible that because the T parameter types are sometimes non-POD, so GCC classes c_Test as non-POD and complains (and complains and complains - I'm getting nearly 800 lines of these warnings).
This is naughty by the strict wording of the standard, since non-POD types can break offsetof. However, this kind of non-POD shouldn't be a problem in practice - c_Test will not have a virtual table, and no run-time trickery is needed to find the offset of m_Test.
Besides, even if c_Test had a virtual table, GCC implements the offsetof macro using an intrinsic that is always evaluated at compile-time based on the static layout of that particular type. Providing a tool then whining (sorry, warning) every time it's used just seems silly.
Also, I'm not the only person around here who does this kind of thing...
Answer to legit-uses-of-offsetof question
I do remember having an issue with offsetof for this kind of reason, but I don't think the problem was this template.
Any ideas?
Oops...
The issue is with the c_Test struct being non-POD due to the T type being non-POD. Here's a quote from the GCC manual...
-Wno-invalid-offsetof (C++ and Objective-C++ only)
Suppress warnings from applying the
‘offsetof’ macro to a non-POD type.
According to the 1998 ISO C++
standard, applying ‘offsetof’ to a
non-POD type is undefined. In existing
C++ implementations, however,
‘offsetof’ typically gives meaningful
results even when applied to certain
kinds of non-POD types. (Such as a
simple ‘struct’ that fails to be a POD
type only by virtue of having a
constructor.) This flag is for users
who are aware that they are writing
nonportable code and who have
deliberately chosen to ignore the
warning about it.
The restrictions on ‘offsetof’ may be
relaxed in a future version of the C++
standard.
My problem is that almost all my T types have constructors, and are therefore classed as non-POD. I ignored this point as irrelevant earlier - and of course it should be irrelevant for offsetof in principle. The trouble is that the C++ standard uses the one POD vs. non-POD classification even though there are a number of distinct ways to be non-POD, and the compiler is correct to warn about non-standards-compliant use by default.
My solution for the moment will be the option above to suppress the warning - now I just need to figure out how to tell cmake to use it.