Why Does Stack<Const String> Not Compile in G++

Why does stackconst string not compile in g++?

The members of a standard container have to be copy assignable or movable (C++11). If the type is const it fails the requirements.

Why does const prevent this from compiling?

A const_iterator is an iterator that points to const value (like a const T* pointer); dereferencing it returns a reference to a constant value (const T&) and prevents modification of the referenced value: it enforces const-correctness.

When you have a const reference to the container, you can only get a const_iterator.

Change the iterator to const_iterator:

std::vector<double>::const_iterator it;

or use auto:

for (auto it = ds.begin(); it != ds.end(); it++) { // Compiler error. No suitable "="
dum = dum + std::to_string(*it) + " ";
}

or range based for loop:

for (auto a: ds)
dum = dum + std::to_string(a) + " ";

Same code compiling in g++, but not in VS

double x1[dim]; is a VLA (variable length array). It is not standard C++.

The reason why it works on gcc is that gcc has an extension which allows VLAs. VS2015 doesn't, so that's why it doesn't compile (it has its own set extensions though, just not that one).

The best alternative is a std::vector:

std::vector<double> x1(dim); //array of size dim

If you can't use that, you can still use a manual dynamic array (although that is not recommended):

double* x1 = new double[dim];
delete[] x1; //Don't forget to delete it when you are done
//Alternatively, create a class which wraps the dynamic array, so you can use RAII

problem with constructors and g++ compile recipe

None of the solutions given above were correct.The problem was within my compilation recipe.These functions started existing after C++11 so if you're using something like that your compilation recipe should be:

g++ -g -std=c++11 -o executable file.cpp main.cpp

Why does not std:string + int give compilation error?

When your colleague only used integer literals, these will be converted to char - You will however see a warning if the value of the integer is too big. The operator that gets called is

std::string operator+(const std::string &s, char c); // actually it's basic_string<> with some CharT...

Or the += variant ;)

On how to find all the calls. You could compile (w/o inlining) all the code, objdump it, grep for all the operator occurrences and use addr2line on the filtered addresses:

$ cat string-plus.cpp
#include <string>
int main()
{
std::string a = "moof ";
a += 192371;
}
$ g++ -g string-plus.cpp
string-plus.cpp: In function ‘int main()’:
string-plus.cpp:5: warning: overflow in implicit constant conversion
$ objdump -Cd a.out | \
grep 'call.*std::string::operator+=(char)@plt' | \
tr -d ' ' | \
cut -d: -f1 | \
xargs addr2line -Cfe string-plus
main
??:0

This however hasn't given me the line number... At least the call site is there ;)

The -C switch enables c++ name demangling. Which can also be done manually with binutls c++filt.


Funnily enough, there is a definition of operator+ for string and char, but only when using operator+= the integer literal is converted to char, I have to pass a char literal (or value) for operator+ to be used.


To find the mangled name of your operator:

$ cat a.cpp
#include <string>
int main()
{
std::string a = "moof ";
a = a + char(1);
}
$ g++ a.cpp
$ objdump -t a.out | c++filt | grep operator+ | cut -d ' ' -f1
08048780
$ objdump -t a.out | grep 0804878
08048780 w F .text 00000067 _ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S3_

The last one is the name you are searching for - which can be used to grep w/o name demangling.

I really don't know a better way to do this... :/

Why do compilers allow string literals not to be const?

The C standard does not forbid the modification of string literals. It just says that the behaviour is undefined if the attempt is made. According to the C99 rationale, there were people in the committee who wanted string literals to be modifiable, so the standard does not explicitly forbid it.

Note that the situation is different in C++. In C++, string literals are arrays of const char. However, C++ allows conversions from const char * to char *. That feature has been deprecated, though.

g++ error in compiling while using std::string[5] as a type in std::map

g++ error in compiling while using std::string[5] as a type in std::map<>

Arrays cannot be stored as elements of std::map. You can store classes though, and arrays can be members of a class. The standard library provides a template for such array wrapper. It's called std::array. You can use that as the element of the map instead.

Sidenote: std::map isn't the only standard container with such limitation. std::array is the only standard container that can itself contain arrays as elements.



Related Topics



Leave a reply



Submit