I have this code which seems to work, but I'm not sure if I'm just seeing undefined behaviour or it's actually working.
#include <string>
#include <vector>
#include <sstream>
#include <numeric>
#include <iostream>
auto main() -> int {
const std::vector<std::string> keywords = {
"and","and_eq","asm","auto","bitand", "bitor","bool","break","case",
"catch","char","class","compl","const", "const_cast","continue",
"default","#define","delete","do","double","dynamic_cast","else","enum",
"explicit","export","extern", "extern \"C\"","false","float",
"for","friend","goto","if","inline","int","long","mutable","namespace",
"new","not","not_eq","operator","or", "or_eq","private","protected",
"public","register","reinterpret_cast","short","signed","sizeof",
"static","static_cast","struct","switch","template","this","throw",
"true","try","typedef","typeid","typename","union","unsigned","using",
"virtual","void","volatile","void","wchar_t","while","xor","xor_eq",
"return", "decltype"
};
std::ostringstream keywords_pattern =
std::accumulate(keywords.begin(), keywords.end(), std::forward<std::ostringstream>(
std::ostringstream("constexpr", std::ostringstream::ate)),
[](std::ostringstream &accum, const std::string& next) -> std::ostringstream&& {
accum << '|' << next;
return std::forward<std::ostringstream>(std::move(accum));
});
std::cout << keywords_pattern.str() << std::endl;
}
What it does:
All this does is combine the vector of C++ keywords into a string seperated by |.
Output:
This is the output when I run it:
onstexpr|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|class|compl|const|const_cast|continue|default|#define|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|extern "C"|false|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|not|not_eq|operator|or|or_eq|private|protected|public|register|reinterpret_cast|short|signed|sizeof|static|static_cast|struct|switch|template|this|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|void|wchar_t|while|xor|xor_eq|return|decltype
No this is not a mistake, it is indeed missing the first character from the output, even though I fail to see how, hence the more reason why I felt certain there was something I was doing wrong.
My concerns:
I am especially worried it might have some undefined behaviour because the function is manipulating a temporary (the ostringstream) through a reference; and finally returning...an rvalue reference??
That's where I need help with understanding how to make sure I am not doing something wrong. Also, with my use of forwarding and move semantics, are there any improvements I can make there? Suggest away.
Compiled with:
Compiles with no warnings or errors on GCC and Clang.
std::accumulate, std::ostringstream and the standard
std::accumulate requires that T (the return type and the type of the initial value) is CopyAssignable and CopyConstructible. std::ostringstream is neither CopyAssignable nor CopyConstructible, so as far as the standard is concerned, it's not allowed. (In fact, MSVC throws a big red error in your face!).
Interestingly, neither GCC nor clang nor icc (the ons i tested) produce even a warning (with -pedantic), though I don't know whether that's a bug (doesn't warn about std::ostringstream not being CopyAssignable or CopyConstructible) or a feature (do they explicitly support move-only types for std::accumulate?).
Anyways, even if they were to support it, it's not in the standard, so they could technically do as they want.
TLDR: It isn't allowed according to the standard.
Implementation
There's no need for std::forward in this code.
In the first usage, the std::ostringstream constructor already returns a rvalue reference.
In the second usage, you already explicitly turned accum into a rvalue reference by calling std::move.
std::forward is useful in templates, where the type of the variable to be forwarded gets deduced, so you don't know whether it can/should be moved or copied. Example:
template<typename T>
void do_something(T&& thing) {
call_impl(std::forward<T>(thing));
}
do_something(std::string("text")); // calls call_impl(std::string&&);
std::string example{"text"};
do_something(example); // calls call_impl(std::string&) or call_impl(const std::string&)
Also, consider replacing std::endl with '\n', unless you explicitly want to flush the stream.
Your issue (the corrupted first character) can be reduced to the following:
#include <string>
#include <sstream>
#include <iostream>
int main()
{
std::ostringstream myStream("constexpr", std::ostringstream::ate);
myStream = std::move(myStream);
std::cout << myStream.str() <<std::endl;
return 0;
}
Which sure looks like a bug in GCC to me.
It works fine in Visual Studio 2013 but the problem is reproduced with
mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev0
Related
FlexeLint/PC-lint is warning about that the return value of std::string::append is not considered on following reduced sample code:
#include <iostream>
#include <string>
int main() {
std::string s("Hell");
s.append(1,'o');
std::cout << s << std::endl;
return 0;
Calling FlexeLint gives the following warning:
Warning 534: Ignoring return value of function 'std::basic_string<char>::append(unsigned long, char)'
While that message is true, it does not make sense to catch the return value in this case because std::string::append simply returns *this.
In addition, any iterators, pointers and references related to this object may be invalidated. But this not the case, no iterators, pointers and references are used.
Question
Did i miss something important or is this simply a false positive of FlexeLint?
PC-Lint is quite flexible and most of the time it's possible to tweak it to your needs. There are several ways to disable this warning:
Using the global option -e534 (covers all functions)
Using the global option -esym(534,std::basic_string<char>::append(unsigned long, char))
Adding the comment //lint !e534 on the same line
I want to modify the string variable present in main function by the external function, by passing the address of the same.
Below is the code which I've written
void change(char * str)
{
str="Max";
}
void main()
{
char a[]="Test";
change(a);
cout<<a;
}
Please correct me if I am wrong
Please note that I am using Borland Turbo C++ 4.5.
I guess you mean pass by reference, you can simply pass the given string by reference to the external function as follows:
void modifyString( string& str)
{
//modify the string
}
inside main, you can call this function.
You want this:
void change(char * str)
{
strcpy(str,"Max");
}
Recall what a pointer is, and that the pointer itself cannot be changed only what it points to.
First of all you should not use Turbo C/C++, It was last updated long time ago,
You can change a string in a function as follows,
void change(char * str)
{
*(str+0)='M';
*(str+1)='A';
*(str+2)='X';
*(str+3)='\0';
}
int main()
{
char a[]="Hello";
change(a) ;
}
You ask,
“correct me if i am wrong”
after presenting this code:
void change(char * str)
{
str="Max";
}
void main() {
char a[]="Test";
change(a);
cout<<a;
}
So, here goes:
str="Max";
only changes the local pointer str. with a compiler conforming to the C++11 standard it won’t even compile, because str is declared as char* while the literal "Max" is of type char const [4], and C++11 does not anymore support an implicit conversion from string literal to pointer to non-const.
void main
will not compile with any standard-conforming C or C++ compiler, no matter which standard. however, visual c++ will compile it with no diagnostic. and possibly old turbo c++ did too, but note that turbo c++ predated the first C++ standard (which came in 1998). the standard requires int result type for main for an ordinary hosted C++ implementation.
cout<<a;
will not compile with a standard-conforming compiler without including <iostream> and having a using declaration or directive. note that this changed with the standardization. before the 1998 standard, in ARM C++, you could include <iostream.h> and use unqualified cout.
A proper way to do your program, in modern C++, is
#include <iostream> // std::cout, std::endl
#include <string> // std::string
using namespace std;
string foo() { return "Max"; }
int main()
{
string a = "Test";
a = foo(); // Changed!
cout << a << endl;
}
another answer, which as I’m writing this you have selected as “solution”, recommends using raw pointers and strcpy, instead of std::string. using raw pointers and arrays is advice that will make you unhappy if you follow it. for example, it’s very easy to inadvertently write beyond the end of the provided buffer, with disastrous effects. ownership handling is exceedingly difficult to do correctly, and so on. the advice was presumably given in the Stack Overflow tradition of answering the literal question with no regard for what the question was really about, which is a good way to obtain Stack Overflow reputation points (it beats me what is so desirable about them, the silly T-shirts or whatever are really not worth it), at the cost of creating severe problems for others, sort of like maiming a few bystanders in order to steal a small bar of chocolate.
I've had a really bizarre problem that I've reduced to the following test case:
#include <iostream>
#include <map>
#include <string>
struct Test
{
std::map<std::string, void (Test::*)()> m;
Test()
{
this->m["test1"] = &Test::test1;
this->m["test2"] = &Test::test2;
}
void test1() { }
void test2() { }
void dispatch(std::string s)
{
if (this->m.at(s) == &Test::test1)
{ std::cout << "test1 will be called..." << std::endl; }
else if (this->m.at(s) == &Test::test2)
{ std::cout << "test2 will be called..." << std::endl; }
(this->*this->m.at(s))();
}
};
int main()
{
Test t;
t.dispatch("test1");
t.dispatch("test2");
}
It outputs
test1 will be called...
test1 will be called...
when optimizations are enabled, which is really bizarre. What's going on?
This is a by-product of what Visual C++ refers to as Identical COMDAT Folding (ICF). It merges identical functions into a single instance. You can disable it by adding the following switch to the linker commandline: /OPT:NOICF (from the Visual Studio UI it is found under Properties->Linker->Optimization->Enable COMDAT Folding)
You can find details at the MSDN article here: /OPT (Optimizations)
The switch is a linker-stage switch, which means you won't be able to enable it just for a specific module or a specific region of code (such as __pragma( optimize() ) which is available for compiler-stage optimization).
In general, however, it is considered poor practice to rely on either function pointers or literal string pointers (const char*) for testing uniqueness. String folding is widely implemented by almost all C/C++ compilers. Function folding is only available on Visual C++ at this time, though increased widespread use of template<> meta-programming has increased requests for this feature to be added to gcc and clang toolchains.
Edit: Starting with binutils 2.19, the included gold linker supposedly also supports ICF, though I have been unable to verify it on my local Ubuntu 12.10 install.
It turns out Visual C++'s linker can merge functions with identical definitions into one.
Whether that's legal or not according to C++, I have no idea; it affects observable behavior, so it looks like a bug to me. Someone else with more information may want to chime in on that though.
C++11 5.3.1 describes what & does; in this instance, it gives you a pointer to the member function in question, and the passage makes no requirement that this pointer must be unique.
However, 5.10/1 says about ==:
Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address.
The question then becomes... are test1 and test2 "the same function"?
Though the optimizer has collapsed them into a single definition, arguably the two names identify two functions and, as such, this would seem to be an implementation bug.
(Note, though, that the VS team don't care and consider it "valid enough" to warrant the benefits of the optimisation. That, or they don't realise that it's invalid.)
I'd stick to using the strings as "handles" for your function pointers.
I'm just wondering what the -fpermissive flag does in the g++ compiler? I am getting:
error: taking address of temporary [-fpermissive]
which I can solve by giving the -fpermissive flag to the compiler.
EDIT:
I just found what was causing the temporary address error part! I'm going to fix that part right now.
Right from the docs:
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings.
Thus, using -fpermissive will allow some nonconforming code to compile.
Bottom line: don't use it unless you know what you are doing!
The -fpermissive flag causes the compiler to report some things that are actually errors (but are permitted by some compilers) as warnings, to permit code to compile even if it doesn't conform to the language rules. You really should fix the underlying problem. Post the smallest, compilable code sample that demonstrates the problem.
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings.
Thus, using -fpermissive will allow some nonconforming code to compile.
When you've written something that isn't allowed by the language standard (and therefore can't really be well-defined behaviour, which is reason enough to not do it) but happens to map to some kind of executable if fed naïvely to the compiling engine, then -fpermissive will do just that instead of stopping with this error message. In some cases, the program will then behave exactly as you originally intended, but you definitely shouldn't rely on it unless you have some very special reason not to use some other solution.
If you want a real-world use case for this, try compiling a very old version of X Windows-- say, either XFree86 or XOrg from aboout 2004, right around the split-- using a "modern" (cough) version of gcc, such as 4.9.3.
You'll notice the build CFLAGS specify both "-ansi" and "-pedantic". In theory, this means, "blow up if anything even slightly violates the language spec". In practice, the 3.x series of gcc didn't catch very much of that kind of stuff, and building it with 4.9.3 will leave a smoking hole in the ground unless you set CFLAGS and BOOTSTRAPCFLAGS to "-fpermissive".
Using that flag, most of those C files will actually build, leaving you free to move on to the version-dependent wreckage the lexer will generate. =]
A common case for simply setting -fpermissive and not sweating it exists: the thoroughly-tested and working third-party library that won't compile on newer compiler versions without -fpermissive. These libraries exist, and are very likely not the application developer's problem to solve, nor in the developer's schedule budget to do it.
Set -fpermissive and move on in that case.
The general answer is that it "Downgrades some diagnostics about nonconformant code from errors to warnings."
Unfortunately, I haven't seen a specific list of things that it allows.
My main reason for posting an answer is to suggest that you avoid using it if at all possible. Instead, look at each error and see if it can be fixed. OP found and fixed what was causing their error. ("taking address of temporary" could be something like calling a function that returns a std::string object, and assigning something to the transient object's c_ptr() value.)
I was just reviewing a project that involved upgrading the version of gcc, and the developer added -fpermissive because there were suddenly a bunch of compilation errors. I noticed that one test was:
if (myPointer == '\0')
I pointed out that it really should be:
if (myPointer[0] == '\0')
The developer checked, and it turned out that every single thing flagged was a real error - some of which had been present for over 20 years.
As #cli_hlt mentioned
Bottom line: don't use it unless you know what you are doing!
It can do horrible things such that a compiler sometimes can cancel of constness of variables for std::map:
#include <map>
#include <vector>
#include <iostream>
#include <string>
struct B{
std::map<std::string, int> m_map;
std::vector<int> m_vector;
B(){
m_map["a"] = 1;
m_map["b"] = 2;
m_map["c"] = 3;
m_vector.emplace_back(1);
m_vector.emplace_back(2);
m_vector.emplace_back(3);
}
const std::map<std::string, int>& getMap() const {
return m_map;
}
const int& getMapValue(const std::string& key) const {
return m_map.at(key);
}
const std::vector<int>& getVector() const {
return m_vector;
}
const int& getVectorValue(const int& i) const {
return m_vector[i];
}
};
int main(){
B b;
auto& my_map = b.getMap(); // we get const ref here
my_map["a"] = 10; // here we can modify it
std::cout << "my_map[a]=" << my_map.at("a") << std::endl;
auto& my_map2 = b.getMap(); // here we return already modified variable
std::cout << "my_map2[a]=" << my_map2.at("a") << std::endl;
auto& my_value = b.getMapValue("b");
// my_value = 20; // compiler error
// std::cout << "my_map[b]=" << my_value << std::endl;
auto& my_vector = b.getVector();
// my_vector[0] = 10; // compiler error
// std::cout << "my_vector[0]=" << my_vector[0] << std::endl;
const int a = 10;
auto& a1 = a;
// a1 = 100; // compiler error
}
As you can see you can't guarantee the constness of the map, however, the constness of a vector or value can be preserved.
P.S. here I tested in the following compilers GCC 12.1, 9.1, 8.1, 7.1, 6.1.
However, clang does not -fpermissive flag have this and it will catch the error.
I've been looking at C++0x threads and have this code:
#include <vector>
#include <iostream>
#include <thread>
void TestFunc(const vector<int>& vVec)
{
cout << "in"<<endl;
}
int main()
{
int sizer = 400000000;
vector<int> vTest(sizer);
for(int f=0; f<sizer; f++)
vTest[f] = f;
cout << "V created." << endl;
thread one(TestFunc, vTest);
one.join();
}
As you can see it just passes a vector to a thread.
The thing I don't understand is that there is a pause after the message "V created" appears. Originally this (I assumed) was the vector being copied for use in the function.
To stop this I passed by reference instead but this made no difference.
The delay seems to be proportional to the size of the vector which indicates that it is still copying (or doing something with the array).
If I try the same experiment without threads and just call the function directly the delay is there when passing by value but not when passing by reference as I expected.
I tried the same using Boost threads instead of C++0x (even though I've read that they are much the same) and got the same result.
Is there some reason for this behaviour or have I missed something blindingly obvious?
Thanks.
Sorry, posted the wrong test code. Corrected.
Edit: Added includes as requested.
Compiled with:
g++44 -std=c++0x -lpthread tester.cpp -o test
...as I have GNU 4.4 installed along side the standard GNU compiler that comes with my Linux (CentOS) which doesn't support C++11.
I'm just speculating, since you haven't posted the version of the code that uses threads, but I would suspect your problem is that, by default, std::bind (or boost::bind) make copies of all the arguments you bind. To avoid this, you can use std::ref or std::cref.
To make this concrete, you're probably using bind like this:
std::bind(TestFunc, vTest)
Instead, you should use it like this:
std::bind(TestFunc, std::cref(vTest));
Where are the threads here? Looks like the for loop is causing the delay you are referring to. Nothing unusual here - as you are assigning a vector of size 200000000.