Question:
what in the world is wrong with this c++ code?
2013-06-14 17:18:19 UTC
is there something i'm missing
or it's just my compiler went mad
can you compile it and run it


#include
#include
#include
using namespace std;
int prev(const string& str)
{

return 4;

}
void main()
{
string g="some thing";
cout< system("pause");

}
Five answers:
?
2013-06-14 17:24:55 UTC
Post the errors and tool chain and/or IDE please. The provided code is valid C++ code (sort of. Standard C++ requires that main must return an int. "void main()" is not standard.)



Note that if building in Visual C++ Express, the source file must have a .cpp or .cxx extension to be built as a C++ file (rather then .c). In addition, performing a clean+rebuild may resolve certain types of errors.



Clean+rebuild

Go to main menu->Build->Rebuild. This performs a clean and rebuild. You can also right click the project in Solution Explorer->Rebuild or Ctrl+Alt+F7 to rebuild all.



The error in question might be solved by declaring g as a const string g="some thing"; in order to avoid a cast from const string to string.
husoski
2013-06-14 18:53:21 UTC
First things first, main() must return an int in C++ (or in Standard C, for that matter).



Change that to "int main()" and add a "return 0;" statement at the end and it runs just fine with the MinGW port of GNU g++.



Edit: Oh, I see.... I tried it on Visual Studio 2010 and indeed this is a Visual C++ 2010 bug.



prev() is a C++11 template function, defined in , and apparently VC++2010 includes this as part of or . GNU g++ is more careful about introducing unwanted names from internal definitions, but both of them seem to include publicly so that system() is visible.



The nasty bit is that the problem persists in VC++2010 even when the usings are removed and explicit std:: references are used on every single name. That amounts to making "prev" a reserved word.



Just changing from prev() to xprev() --- a quick hack, not a suggestion --- fixed the problem.



The practical solution is to change the name from prev() to something else. Just changing from prev() to xprev() --- a quick hack, not a suggestion --- fixed the problem.



There's also a "next()" template, with the same problem.



Also, FWIW, the problem still exists in Visual Studio 2012 Express, but is not not present in VC++2008 (where the C++11 features were still in the std::tr1:: namespace.)



Edit: @RatchetR--You may get more names from the std:: namespace that you explicitly included because headers may include other headers. GNU is pretty clean about not doing that, much, and Visual C++ is comparatively sloppy about it. That creates a problem when names are referenced without including the proper header. VC++ will compile the program (after changing prev to something else) even without including , and both g++ and VC++ accepted system() without an explicit include of .



The standard allows headers to include other headers, and requires it in some cases. Except in the required cases, though, the standard also says that a program is ill-formed if it doesn't include the proper header before using a library feature. This is all far from ideal. It's common for very simple programs to compile without warning on VC++ and fail on g++ because of the extra includes.



The bug part is that the definitions of next() and prev() are leaking out to the global namespace, so that fixing the "using namespace std;" issue does not make the error go away. I wasn't clear about that, I guess.
David
2013-06-14 18:47:38 UTC
You're unnecessarily including the header, which boasts itself a function with the exact same name as yours. Here is the prototype of the function inside the std namespace:



    template< class BidirIt >

    BidirIt prev( BidirIt it,

        typename std::iterator_traits< BidirIt >::difference_type n = 1 );



This is a standard library function used for accessing, as cppreference puts it, the n-th predecessor of `it`, which can be any object that has an iterator.



Since you entered the function into the global scope by using "using namespace std", it becomes a candidate for something called overload resolution. These are a set of overloaded functions taking different parameters, which the compiler attempts to select based on the arguments passed.



When I compile your code as you've shown it above, the compiler I'm using chooses your version of prev. But when I change the parameter of prev to int, it goes with std::prev because it's first parameter is templated, but then it creates an error for the second (default) argument because it tries to construct an integer from std::iterator_traits when int doesn't contain an iterator.



However, by what you're telling me, it seems Visual Studio is selecting the templated version of prev instead of your version even though yours is more specialized (your version explicitly takes a std::string while std::prev does not). I'm assuming this is a bug in Visual Studio.



A solution would be to get rid of the "using namespace std" line and use std::prev or prev for your version.
Ratchetr
2013-06-14 18:44:24 UTC
There is a risk when you add this line of code to a C++ program:

using namespace std;



It means you are exposing the entire std namespace. That does make things cleaner and easier most of the time, since you don't have to write std:: all the time. Let's face it, this is ugly:

std::cout<< prev(g) <


But the risk when you do that is name collision. You happened to choose a function name, prev, that also exists in the std namespace (see link). And the signature of your prev function just happens to be close enough to the signature for std::prev that the compiler wants to use std::prev. But it can't quite get there, and issues the typical impossible for most humans to read or understand C++ error message.



3 ways to fix it:

1) Get rid of using namespace std, then prefix things like cout with std::

2) Change the name of your prev function to something else (that isn't already used in std).

2) Use :: to reference g in the global namespace:

cout << ::prev(g) <


(There are other ways to fix it as well, but those are the simplest I can think of).



ETA: @husoski. Enjoyed reading your answer. I haven't written C++ code for a living for close to a decade, but I still try to keep up with the language. I'm curious about 1 point: Once you bring in the std namespace, aren't you really saying you accept the entire scope of the namespace? Or are you supposed to be guaranteed that you only get the subset of the namespace that comes directly from the files you include? Microsoft is obviously #including other things on your behalf here, which introduces more of the std namespace, including prev. But is that really a bug? If g++ just happens to bring in a smaller subset of the namespace, is that really a Microsoft bug? (I'm really not trying to be argumentative here. I honestly don't know what the rules are. But I'm thinking that once you start using namespace std, the compiler is free to give you the entire namespace? Regardless of what you #include? Does the spec address this?)
?
2016-12-13 23:47:38 UTC
cut back and paste, your code works on gcc 4.2.4 engaged on Debian lenny/sid. Is there any reason you won't be in a position to easily placed up utilising namespace std; up there between your #comprise and considerable? then you certainly does no longer ought to specify the place cout and endl are and it could be lots extra readable. Oh. i don't be attentive to what compiler you're utilising or what OS yet cout, endl AND the << operator are ALL declared in iostream so as that they are ALL area of the std namespace. My compiler created an executable which printed hi worldwide! to cout (time-honored output) without variations in the code. it quite is yours is amazingly choosy, and in case you ought to declare all the tokens in std for my area you disregarded one, yet returned, utilising that namespace makes for extra readable code.


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...