Problems with remove_if in VS2010 when using sets - visual-studio-2010

I have the following code.
#include <set>
#include <algorithm>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
typedef set<long> MySet;
MySet a;
for( int i = 0; i < 10; ++i)
{
a.insert(i);
}
MySet::iterator start,end,last;
start = a.begin();
end = a.end();
last = remove_if(start,end,bind2nd(less_equal<long>(),5));
return 0;
}
Which under VS2005 used to compile fine. However using VS2010 I get the following error:
Error 1 error C3892: '_Next' : you cannot assign to a variable that is const c:\program files\microsoft visual studio 10.0\vc\include\algorithm
If I make the container a vector, everything is fine.
I'm guessing something has changed in the standard that I'm not aware of, can someone please shed some light on why this no longer works?

A std::set always keeps its elements in sorted order. std::remove_if attempts to move the elements you don't want removed to the beginning of the collection. This would violate set's invariant of maintaining the elements in sorted order.
The code never should have worked. Older compilers might not have enforced the rules tightly enough to let you know that it wasn't supposed to work, but (apparently) your current one does.

Related

Directly assigning to a std::vector after reserving does not throw error but does not increase vector size

Let's create a helper class to assist visualizing the issue:
class C
{
int ID = 0;
public:
C(const int newID)
{
ID = newID;
}
int getID()
{
return ID;
}
};
Suppose you create an empty std::vector<C> and then reserve it to hold 10 elements:
std::vector<C> pack;
pack.reserve(10);
printf("pack has %i\n", pack.size()); //will print '0'
Now, you assign a new instance of C into index 4 of the vector:
pack[4] = C(57);
printf("%i\n", pack[4].getID()); //will print '57'
printf("pack has %i\n", pack.size()); //will still print '0'
I found two things to be weird here:
1) shouldn't the assignment make the compiler (Visual Studio 2015, Release Mode) throw an error even in Release mode?
2) since it does not and the element is in fact stored in position 4, shouldn't the vector then have size = 1 instead of zero?
Undefined behavior is still undefined. If we make this a vector of objects, you would see the unexpected behavior more clearly.
#include <iostream>
#include <vector>
struct Foo {
int data_ = 3;
};
int main() {
std::vector<Foo> foos;
foos.reserve(10);
std::cout << foos[4].data_; // This probably doesn't output 3.
}
Here, we can see that because we haven't actually allocated the object yet, the constructor hasn't run.
Another example, since you're using space that the vector hasn't actually started allocating to you, if the vector needed to reallocate it's backing memory, the value that you wrote wouldn't be copied.
#include <iostream>
#include <vector>
int main() {
std::vector<int> foos;
foos.reserve(10);
foos[4] = 100;
foos.reserve(10000000);
std::cout << foos[4]; // Probably doesn't print 100.
}
Short answers:
1) There is no reason to throw an exception since operator[] is not supposed to verify the position you have passed. It might do so in Debug mode, but for sure not in Release (otherwise performance would suffer). In Release mode compiler trusts you that code you provide is error-proof and does everything to make your code fast.
Returns a reference to the element at specified location pos. No
bounds checking is performed.
http://en.cppreference.com/w/cpp/container/vector/operator_at
2) You simply accessed memory you don't own yet (reserve is not resize), anything you do on it is undefined behavior. But, you have never added an element into vector and it has no idea you even modified its buffer. And as #Bill have shown, the vector is allowed to change its buffer without copying your local change.
EDIT:
Also, you can get exception due to boundary checking if you use vector::at function.
That is: pack.at(4) = C(57); throws exception
Example:
https://ideone.com/sXnPzT

G++ -cilkplus random behavior with std::vectors

The following (reduced) code is very badly handled by the series of GCC
#include <vector>
#include <cilk/cilk.h>
void walk(std::vector<int> v, int bnd, unsigned size) {
if (v.size() < size)
for (int i=0; i<bnd; i++) {
std::vector<int> vnew(v);
vnew.push_back(i);
cilk_spawn walk(vnew, bnd, size);
}
}
int main(int argc, char **argv) {
std::vector<int> v{};
walk(v , 5, 5);
}
Specifically:
G++ 5.3.1 crash:
red.cpp: In function ‘<built-in>’:
red.cpp:20:39: internal compiler error: in lower_stmt, at gimple-low.c:397
cilk_spawn walk(vnew, bnd, size);
G++ 6.3.1 create a code which works perfectly well if executed on one core
but segfault sometime, signal a double free some other times if using more cores. A student who
has a arch linux g++7 reported a similar result.
My question : is there something wrong with that code. Am I invoking some
undefined behavior or is it simply a bug I should report ?
Answering my own question:
According to https://gcc.gnu.org/ml/gcc-help/2017-03/msg00078.html its indeed a bug in GCC. The temporary is destroyed in the parent and not in the children in a cilk_spawn. So if the thread fork really occur, it might be destroyed too early.

C++11 container of borrowed unique_ptrs

I have a vector of unique_ptrs and want to filter it into a new vector of the same type.
vector<unique_ptr<Thing>> filter_things(const vector<unique_ptr<Thing>> &things) {
vector<unique_ptr<Thing>> things;
// i want the above line to be something like: vector<const unique_ptr<Thing> &>
// but I don't think this is valid
for (const unique_ptr<Thing> &thing : things) {
if (check(thing)) {
filtered.push_back(thing); // this part shouldn't work since it
// would duplicate a unique_ptr
}
}
return filtered;
}
I want the caller to maintain ownership of all the Things. I want the return value of this function to be purely read only (const), and I don't want to make copies as it is very expensive to copy a Thing.
What is the best way to accomplish this?
Is this possible with unique_ptrs?
In some sense, we are creating multiple references by returning a new vector of references, so unique_ptr may not make sense. However, it is purely read only! So there should be some way to make this work. The lifetime of ``things'' is guaranteed to be larger than the filtered things.
Note that the caller owns the parameter supplied.
You can use reference_wrapper from <functional>
#include <memory>
#include <functional>
#include <vector>
#include <iostream>
using namespace std;
struct Thing {};
using PThing = unique_ptr<Thing>;
using RefThing = reference_wrapper<const PThing>;
vector<RefThing> filter_things( const vector<PThing>& things )
{
vector<RefThing> filtered;
int i = 0;
for( auto&& thing : things )
{
if( i++%2 )
filtered.push_back( ref(thing) );
}
return filtered;
}
int main()
{
vector<PThing> vec;
vector<RefThing> flt;
vec.resize(25);
flt = filter_things(vec);
cout << flt.size() << endl;
}
If what you want is getting a filtered set of element not an actual container containing them, boost::range can be a good solution.
auto filtered_range(const std::vector<std::unique_ptr<Thing>> &things) {
return things | boost::adaptors::filtered([](const auto& thing) {
return check(thing);
});
}
I used some of c++14 syntax but I don't think it's hard to make it to c++11.
You can use it like this.
std::vector<std::unique_ptr<Thing> > things;
for(const auto& thing : filtered_range(things)) {
// do whatever you want with things satisfying 'check()'
}
One of disadvantages is that the range itself is not a container so if you traverse the range more than once, every 'thing' will be checked if it satisfies check().
If a container storing the checked things AND controlling the lifetime of things are what you really want, I would prefer using std::vector<std::shared_ptr<Thing> > and returning std::vector<std::weak_ptr<Thing> >. You can check if it's really one and the only ptr to a thing with std::shared_ptr::unique() before deleting it from things.

Visual C++ find out max possible value of variable's data type

I am using VS2010 to port an existing Mac application written in C++ to Windows. The following line of code:
T var_max;
var_max = std::numeric_limits<typeof(var_max)>::max();
given a variable, determines the maximum value for the data type of that variable.
How do I write equivalent code in VC++? I tried using typeid to determine the data type, but it only gives out a string and cannot be used in a template.
You don't need to determine the data type. It's T. Try this code:
#include <limits>
template <typename T>
T MaxValue()
{
T var_max = (std::numeric_limits<T>::max)();
return var_max;
}
int _tmain(int argc, _TCHAR* argv[])
{
int value = MaxValue<int>();
return 0;
}

Dereferencing void* warnings on Xcode

I'm aware of this SO question and this SO question. The element
of novelty in this one is in its focus on Xcode, and in its use of
square brackets to dereference a pointer to void.
The following program compiles with no warning in Xcode 4.5.2, compiles
with a warning on GCC 4.2 and, even though I don't have Visual Studio
right now, I remember that it would consider this a compiler
error, and MSDN and Internet agree.
#include <stdio.h>
int main(int argc, const char * argv[])
{
int x = 24;
void *xPtr = &x;
int *xPtr2 = (int *)&xPtr[1];
printf("%p %p\n", xPtr, xPtr2);
}
If I change the third line of the body of main to:
int *xPtr2 = (int *)(xPtr + 1);
It compiles with no warnings on both GCC and Xcode.
I would like to know how can I turn this silence into warnings or errors, on
GDB and especially Xcode/LLVM, including the fact that function main is int but
does not explicitly return any value (By the way I think -Wall does
the trick on GDB).
that isnt wrong at all...
the compiler doesnt know how big the pointer is ... a void[] ~~ void*
thats why char* used as strings need to be \0-terminated
you cannot turn on a warning for that as it isnt possible to determine a 'size of memory pointer to by a pointer' at compile time
void *v = nil;
*v[1] = 0 //invalid
void *v = malloc(sizeof(int)*2);
*v[1] = 0 //valid
*note typed inline on SO -- sorry for any non-working code

Resources