4

I have to maintain a program that nobody has touched since 2004.

class CSolver
{  
 ...  
 ClauseIdx add_clause (int * lits, int n_lits);
}

void and2 (CSolver & solver)   
{  
vector <int> lits;  
...  
solver.add_clause(lits.begin(), lits.size());  
}

The compiler complains that:

error: no matching function for call to ‘CSolver::add_clause(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, size_t)’

I try to cast it

solver.add_clause((int*)lits.begin(), lits.size());

But there is still a complaint:

error: invalid cast from type ‘__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >’ to type ‘int*’

I want to look for a quick fix on this, because changing interface of CSolver will result changing the whole program.

Thanks in advance.

ephemient
  • 198,619
  • 38
  • 280
  • 391
sean
  • 1,632
  • 2
  • 15
  • 34

5 Answers5

11

Like this:

solver.add_clause(lits.data(), lits.size());

Don't add casts without understanding what you're doing.

The function wants an array of ints, and it's asking for them by a pointer to the first element along with a size. This is a common C convention.

Lucky for us, std::vector stores elements precisely as a contiguous array, so we can get a pointer to the first element (lits.data(), &lits[0], &lits.front(), etc.) and then just pass the size.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
7

If you can compile against c++11, you can use

solver.add_clause(lits.data(), lits.size());

http://en.cppreference.com/w/cpp/container/vector/data

tomahh
  • 13,441
  • 3
  • 49
  • 70
4

This should work on multiple platforms without C++11 support:

solver.add_clause(&lits[0], lits.size());

Edit: The assumptions here being you just want to satisfy the API and you have resized the vector to have enough ints allocated for the operation and that the add_clause method is not going to muck with pointers, allocate new integers, or otherwise violate the heap.

The reason for this workaround being possible is due to the vector's internal contiguous allocation on the heap so a pointer to the first element is sufficient to use the container as an array for c-style iteration of elements as long as you note the amount of elements.

AJG85
  • 15,849
  • 13
  • 42
  • 50
  • I thought `data` (from the other answers) existed before C++11, did it change somehow? – Mark Ransom Sep 11 '13 at 20:54
  • Yes, but it was not available in all implementations of STL which was a concern for developers that needed to support compilation on many platforms. C++11 standardized the method so now the question is do you need to support older compilers that might not have it? – AJG85 Sep 11 '13 at 21:15
2

You can just use like this to avoid of casting:

solver.add_clause(&(*lits.begin()), lits.size())

Here, take the *list.begin() and get its address, the address is a int *

BigTailWolf
  • 1,028
  • 6
  • 17
0

Not so fast dear. Of course you can apply the solution already expressed by others:

solver.add_clause(lits.data(), lits.size());

or my preferred choice :

solver.add_clause(&lits[0], lits.size());

which designates that something uncommon goes on here,

but you should first consider that even if the standard defines that vector internal storage should be contiguous , this does not mean it is not reallocatable. Unfortunately the latter happens quite often.

Community
  • 1
  • 1
g24l
  • 3,055
  • 15
  • 28