I'm compiling the following C++ code in Visual Studio 2015 (update 3):
#include <iostream>
using namespace std;
////////////////////////////////////////
#define UNDERSCORE1(a,b) a ## _ ## b
#define UNDERSCORE(a,b) UNDERSCORE1(a,b)
#define STRINGIFY1(x) #x
#define STRINGIFY(x) STRINGIFY1(x)
#define VALUE(x) UNDERSCORE(x, VALUE)
#define NEXT(x) (VALUE(x) + 1)
/////////////////////////////////////////
#define X1_VALUE 0
#define X2_VALUE NEXT(X1)
#define X3_VALUE NEXT(X2)
#define TOTAL NEXT(X3)
int main() {
cout << STRINGIFY(TOTAL) << endl;
cout << TOTAL << endl;
return 0;
}
The result printed to stdout is very strange:
(X3_VALUE + 1)
3
When trying the same on gcc, build fails (expectedly).
When commenting out cout << TOTAL << endl; I get something different altogether:
(NEXT(X2) + 1)
Actually gcc behavior makes sense, since NEXT macro is called recursively: NEXT(X3) is expanded to X3_VALUE which in turn expands to NEXT(X2), so the second expansion of NEXT macro (NEXT(X2)) is not performed.
What doesn't make sense is Visual Studio behavior:
When printing the macro TOTAL using STRINGIFY, NEXT seems to be expanded twice to yield X3_VALUE.
When compiling the macro TOTAL directly to send it to cout, NEXT is expanded all the way! As if the preprocessor ran multiple times to recursively expand NEXT.
Another thing I tried was to compile this code in Visual Studio with the /P compiler option, to get the preprocessed code:
int main() {
cout << "(X3_VALUE + 1)" << endl;
cout << (((0 + 1) + 1) + 1) << endl;
return 0;
}
So is it, as I suspect, a bug in Visual Studio preprocessor? Or a legit undefined behavior?
Perhaps this behavior can be abused to truly expand macros recursively? I know that a limited recursion is possible with some tricks but is limited to a predefined number of scans. In this case I did not observe a limit to the number of times NEXT is expanded.
As Hans mentioned in the comments, the MSVC preprocessor is not conformant.
You can enable the conformant preprocessor with -experimental:preprocessor.
Here is a simplified repro + solution: https://godbolt.org/z/7u_-bH
Related
Everytime I use the terminal to print out a string or any kind of character, it automatically prints an "%" at the end of each line. This happens everytime I try to print something from C++ or php, havent tried other languages yet. I think it might be something with vscode, and have no idea how it came or how to fix it.
#include <iostream>
using namespace std;
int test = 2;
int main()
{
if(test < 9999){
test = 1;
}
cout << test;
}
Output:
musti#my-mbp clus % g++ main.cpp -o tests && ./tests
1%
Also changing the cout from cout << test; to cout << test << endl; Removes the % from the output.
Are you using zsh? A line without endl is considered a "partial line", so zsh shows a color-inverted % then goes to the next line.
When a partial line is preserved, by default you will see an inverse+bold character at the end of the partial line: a ‘%’ for a normal user or a ‘#’ for root. If set, the shell parameter PROMPT_EOL_MARK can be used to customize how the end of partial lines are shown.
More information is available in their docs.
I need to create a hyper link in my comments section of my c++ code so that , when I click on the link, it should take me to a specific line of the same code base.
That specific line could be in same file or different, but of course the same project.
Is this possible in Visual studio when writing c/c++ code.
For example,
int main()
{
Marks m1(10,20);
Marks m2(30,40);
Marks m3,m4;
//Line 7
std::cout <<m1.get_int_marks()<<std::endl;
std::cout << m1.get_ext_marks() << std::endl;
m3 = m1 + m2;
//Line 14
std::cout << m3.get_int_marks() << std::endl;
std::cout << m3.get_ext_marks() << std::endl;
m4 = m1 - m2;
int x = 10 + 20;
std::cout << m4.get_int_marks() << std::endl;
std::cout << m4.get_ext_marks() << std::endl;
std::cout << x << std::endl;
return 0;
}
In the above code , can I create a hyperlink in the comments, at line 7 to go to line 14.
Used case can be to go to any line of any file in the project.
Thanks in advance.
In case you want a link to method, you can use empty function macro to prevent compiler warnings, privates, etc.
Put pseudo code inside and follow by F12 (Visual Studio) or similar key elsewhere.
Includes are often mandatory for jump to wanted method directly.
#define CALLERS(...)
#include "myClass.h"
#include "myFunctions.h"
CALLERS(myClass::myMethod; function();)
I am trying to perform run length compression on a string for a special protocol that I am using. Runs are considered efficient when the run size or a particular character in the string is >=3. Can someone help me to achieve this. I have live demo on coliru. I am pretty sure this is possible with the standard library's std::adjacent_find with a combination of std::not_equal_to<> as the binary predicate to search for run boundaries and probably using std::equal_to<> once I find a boundary. Here is what I have so far but I am having trouble with the results:
Given the following input text string containing runs or spaces and other characters (in this case runs of the letter 's':
"---thisssss---is-a---tesst--"
I am trying to convert the above text string into a vector containing elements that are either pure runs of > 2 characters or mixed characters. The results are almost correct but not quite and I cannot spot the error.
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
expected the following
======================
---,thi,sssss,---,is-a,---,tesst--,
actual results
==============
---,thi,sssss,---,is-a,---,te,ss,--,
EDIT: I fixed up the previous code to make this version closer to the final solution. Specifically I added explicit tests for the run size to be > 2 to be included. I seem to be having boundary case problems though - the all spaces case and the case where the end of the strings ends in several spaces:
#include <iterator>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
int main()
{
// I want to convert this string containing adjacent runs of characters
std::string testString("---thisssss---is-a---tesst--");
// to the following
std::vector<std::string> idealResults = {
"---", "thi", "sssss",
"---", "is-a",
"---", "tesst--"
};
std::vector<std::string> tokenizedStrings;
auto adjIter = testString.begin();
auto lastIter = adjIter;
// temporary string used to accumulate characters that
// are not part of a run.
std::unique_ptr<std::string> stringWithoutRun;
while ((adjIter = std::adjacent_find(
adjIter, testString.end(), std::not_equal_to<>())) !=
testString.end()) {
auto next = std::string(lastIter, adjIter + 1);
// append to foo if < run threshold
if (next.length() < 2) {
if (!stringWithoutRun) {
stringWithoutRun = std::make_unique<std::string>();
}
*stringWithoutRun += next;
} else {
// if we have encountered non run characters, save them first
if (stringWithoutRun) {
tokenizedStrings.push_back(*stringWithoutRun);
stringWithoutRun.reset();
}
tokenizedStrings.push_back(next);
}
lastIter = adjIter + 1;
adjIter = adjIter + 1;
}
tokenizedStrings.push_back(std::string(lastIter, adjIter));
std::cout << "expected the following" << std::endl;
std::cout << "======================" << std::endl;
std::copy(idealResults.begin(), idealResults.end(), std::ostream_iterator<std::string>(std::cout, ","));
std::cout << std::endl;
std::cout << "actual results" << std::endl;
std::cout << "==============" << std::endl;
std::copy(tokenizedStrings.begin(), tokenizedStrings.end(), std::ostream_iterator<std::string>(std::cout, ","));
std::cout << std::endl;
}
if (next.length() < 2) {
if (!stringWithoutRun) {
stringWithoutRun = std::make_unique<std::string>();
}
*stringWithoutRun += next;
}
This should be if (next.length() <= 2). You need to add a run of identical characters to the current token if its length is either 1 or 2.
I seem to be having boundary case problems though - the all spaces
case and the case where the end of the strings ends in several spaces
When stringWithoutRun is not empty after the loop finishes, the characters accumulated in it are not added to the array of tokens. You can fix it like this:
// The loop has finished
if (stringWithoutRun)
tokenizedStrings.push_back(*stringWithoutRun);
tokenizedStrings.push_back(std::string(lastIter, adjIter));
C++11
I'm having trouble using the move constructor. I have a simple container class, called Number, whose only data member is an integer. I have the following code:
//Number.h
#ifndef NUMBER_H
#define NUMBER_H
#include <iostream>
class Number
{
public:
Number();
Number(int ipar);
Number(const Number& src);
Number(Number&& src);
private:
int num;
};
#endif
and
//Number.cpp
#include "Number.h"
Number::Number()
{
std::cout << "default ctor" << std::endl;
}
Number::Number(int ipar) : num(ipar)
{
std::cout << "integer argument ctor" << std::endl;
}
Number::Number(const Number& src) : num(src.num)
{
std::cout << "copy ctor" << std::endl;
}
Number::Number(Number&& src) : num(src.num)
{
std::cout << "move ctor" << std::endl;
}
and
//main.cpp
#include "Number.h"
using namespace std;
int main()
{
cout << "Part A:" << endl;
Number n1(1);
cout << "Part B:" << endl;
Number n2(n1);
cout << "Part C:" << endl;
Number n3{Number{n1}};
cout << "Part D:" << endl;
Number n4(Number(n1));
return 0;
}
This outputs:
Part A:
integer argument ctor
Part B:
copy ctor
Part C:
copy ctor
Part D:
Notice there is no output for Part D. The output for Parts A and B are what I expected, but the output for the others aren’t.
I expected this for Parts C and D:
Part C:
copy ctor
move ctor
Part D:
copy ctor
move ctor
Expectation for Part C:
I expected the Number{n1} part of Number n3{Number{n1}} to make a temporary nameless Number object, because there is no name between Number and the opening curly brace, by calling the copy constructor with n1. Then I expected Number n3 to be constructed by calling the move constructor with the temporary object.
Expectation for Part D:
Since this is like Part C, except with parentheses instead of curly braces, I expected this part to behave and output in the same way I expected Part C to.
Question:
Why does the actual output differ from my expectations and what is the correct way to get my desired output?
Note: If you want to compile this in Visual Studio, you need the Visual C++ Compiler November 2012 CTP or later for Visual Studio 2012 in order to support the uniform initialization syntax.
n4 is a function declaration. n3 is caused by copy elision.
Check that here I've enabled -fno-elide-constructors to avoid copy elision. n3 then shows a sequence of copy and move constructors.
There's a commented out line that tries to use n4 as an object. If you uncomment it, you'll see the compiler error telling it's a function instead.
For n4 do not be interpreted as a function declaration you could put extra parentheses around the temporary to prevent it from being viewed as a function parameter: Number n4((Number(n1))). With this and -fno-elide-constructors all you've expected happens.
Note that -fno-elide-constructors is not present as an option in MSVC.
I've seen this, but none of the answers worked for VS2010. The constant's (or should I call it variable?) numerical value didn't get displayed
This line of code #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX is turning out to be true when I'm actually programming in windows. I need to see the value of OGRE_PLATFORM_WIN32 and OGRE_PLATFORM_LINUX during the build process itself. Could you help with how to go about it?
You can check the preprocessor output using:
/E - preprocess to stdout or
/P - preprocess to file or
/EP - preprocess to stdout without #line directives
options in visual studio
First, check the preprocessor defines in project options - active configuration and all configurations, and make sure the right things are defined.
If you are still having problems, try substituting this for your main method:
#include <iostream>
int main()
{
#ifdef OGRE_PLATFORM_LINUX
std::cout << "OGRE_PLATFORM_LINUX = " << OGRE_PLATFORM_LINUX << "\n";
#else
std::cout << "OGRE_PLATFORM_LINUX not defined.\n";
#endif
#ifdef OGRE_PLATFORM_WIN32
std::cout << "OGRE_PLATFORM_WIN32 = " << OGRE_PLATFORM_WIN32 << "\n";
#else
std::cout << "OGRE_PLATFORM_WIN32 not defined.\n";
#endif
#ifdef OGRE_PLATFORM
std::cout << "OGRE_PLATFORM = " << OGRE_PLATFORM << "\n";
#else
std::cout << "OGRE_PLATFORM not defined.\n";
#endif
return 0;
}
Also, did you create the project, was it created by some type of pre-make (CMake, automake, etc) system, did you download it from somewhere? If you didn't create it, somebody could have ported over some Linux code without checking their preprocessor options.