I am using visual studio 2017. In C++, I tried to assign a pointer to 'this' pointer. It showed compiler error as "assignment to 'this' (anachronism)". Anachronism means adding something into the period it can't exist like roman emperor checks computer. So is the compiler warning also like this. Or is there any specific meaning in coding for the word "anachronism"?.
A good while ago, this pointer could be assigned values. I met such assignments in the code of the Cfront compiler. I wrote about it in this note: Celebrating the 30-th anniversary of the first C++ compiler: let's find the bugs in it. Examples:
expr.expr(TOK ba, Pexpr a, Pexpr b)
{
register Pexpr p;
if (this) goto ret;
....
this = p;
....
}
inline toknode.~toknode()
{
next = free_toks;
free_toks = this;
this = 0;
}
Anachronism is something that was OK long time ago but not anymore.
Starting from C++98, this is an rvalue and as such cannot be assigned (i.e. cannot appear on the left from an assignment operator).
See §9.3.2 The this pointer:
In the body of nonstatic (9.3) member function, the keyword this is a non-lvalue expression whose value is the address of the object for which the function is called.
Starting from C++11, this is specified as a prvalue.
From google:
a thing belonging or appropriate to a period other than that in which it exists, especially a thing that is conspicuously old-fashioned.
Which basically means that this used to be allowed in the past (probably by pre standards compliant compilers) but isn't allowed anymore.
This question tapped my curiosity, so I dug into my copies of all the ratified C++ standards and technical corrigenda I have (which works out to everything between C++98 and C++17 inclusive). None of them contain the word "anachronism" in any form.
The ARM (The C++ Annotated Reference Manual) by Ellis and Stroustrup, 1990 (a base document written to guide development of the C++ standard) has Section 18.3 entitled "Anachronisms". The first paragraph of that section says
The extensions provided here may be provided by an implementation to ease the use of C programs as C++ programs or to provide continuity from earlier C++ implementations. Note that each of these features has undesirable aspects. An implementation providing them should also provide a way for the user to ensure that they do not occur in a source file. A C++ implementation is not obliged to provide these features.
Related
C++11 allows initializing a value with zero using the expression T(); (http://en.cppreference.com/w/cpp/language/zero_initialization). Is this feature supported by Visual Studio 2010? I ran some experiments comparing T x; with T x = T(); and I concluded that the latter case does initialize the value with zero, but I am not sure whether I can rely on that.
Is zero initialization mentioned anywhere in the VS2010 documentation? The VS2010 Initializers page (https://msdn.microsoft.com/en-us/library/w7wd1177(v=vs.100).aspx) does not mention it, unlike pages for later versions, e.g., VS2013 (https://msdn.microsoft.com/en-us/library/w7wd1177(v=vs.120).aspx).
This is a fundamental behaviour of the language that has been in there since the start. It was not introduced in C++11 (on that cppreference page note that "since C++11" is aligned with only the third of the examples under usage (2); granted it's not very clear).
If T were int and T() did not result in a temporary int of value zero (and this is zero-initialisation via value-initialisation), the compiler would have a very serious bug. I am sure that Visual Studio does not have this bug.
As for proof, the VS2010 docs do not seem to mention this behaviour in the same place the standard mentions it (i.e. under the explicit type conversion expression section). It is certainly possible that their documentation has changed/evolved/become more thorough over time, though, particularly as C++ itself added more and more ways to initialise things.
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...
Is a type specifier required here?
const c = 7;
Bjarne Stroustrup's 'The C++ Programming Language' on page 80 says that this is illegal. However, I've been practicing some brainbench tests, and one of the questions states that the type defaults to int. Brainbench is usually correct, so I'm unsure of which reference is right, and I've been unable to find anything in the standard. Does anyone have a definitive answer and a reference?
The default type of int is valid for C, but not for C++. Even in C this style of coding should be avoided. Also note that Bjarne Stroustrup's book is one of the most authoritative reference for standard C++.
For C++ I would believe Stroustrup over any place but a standard.
Perhaps the question was about C not C++?
The draft C++0x standard in section 7.1.6 says
At least one type-specifier that is not a cv-qualifier is required in a declaration unless it declares a constructor,
destructor or conversion function.83 A type-specifier-seq shall not define a class or enumeration unless it
appears in the type-id of an alias-declaration (7.1.3).
I can't speak to the standard... but just looking at a statement like const c = 7; screams bad code style to me. As far as compiler compatibility... it's probably going to be hit-and-miss. Microsoft Visual Studio's compiler won't have any part of it when compiling a C++ file (.cpp extension) but doesn't choke on it when compiling a C file (.c extension) mainly because the C standard allows for defaulting variables as int when no type is specified.
Hi i have to port some stuff written on c++ from unix bases os to windows visual studio 2008.
The following code implements array data type with void ** - pointer to the data.
struct array
{
int id;
void **array; // store the actual data of the array
// more members
}
When i compile with g++ on Unix it's ok but when i try with MSVS 2008 I get the error - error C2461: 'array' : constructor syntax missing formal parameters. When i change the member from 'array' to something else it works, so it seems that the compiler thinks that the member name 'array' is actually the constructor of the struct array. It's obviously not a good practice to name the member like the struct but it's already written that way. Can i tell the MSVS compiler to ignore this problem or i should rename all members that are the same as the struct name.
You are dealing with a bug in GCC compiler. C++ language explicitly prohibits having data members whose name is the same as the name of the class (see 9.2/13). MS compiler is right to complain about it. Moreover, any C++ compiler is required to issue a diagnostic message in this case. Since GCC is silent even in '-ansi -pedantic -Wall' mode, it is a clear bug in GCC.
Revison: What I said above is only correct within the "classic" C++98 specification of C++ language. In the most recent specification this requirement only applies to static data members of the class. Non-static data members can now share the name with the class. I don't know whether this change is already in the official version of the revised standard though.
That means that both compilers are correct in their own way. MS compiler sticks to the "classic" C++98 specification of the language, while GCC seems to implement a more recent one.
I'd say that if you're doing something that you yourself describe as "not a good practice", then you should change it.
I would rename your attribute to not have the same name as the class. This will make your code more portable. If you have to move to yet another compiler in the future, you won't run in to this problem again then.