I would like to add an open ofstream as a class (Barcode) attribute. The goal is to implement several Barcodes in my main() that will each be able to write into a specific file. Also, I decided to stock all the barcodes in a vector, which belongs to a Barcodes class, although it is maybe not useful.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sys/stat.h>
using namespace std;
class Barcode {
public:
// Constructor
Barcode(string bcName, string bcSeq, string end, string const & fileName):
m_bcName(bcName), m_bcSeq(bcSeq), m_end(end), m_ofStream(fileName.c_str(), ios::app) {}
// Getters
string getBCName() const {
return m_bcName;
}
string getBCSeq() const {
return m_bcSeq;
}
//setter
void reportRead(string toReport) {
m_ofStream << toReport;
}
private:
string m_bcName;
string m_bcSeq;
string m_end;
ofstream m_ofStream;
};
class Barcodes {
public:
// Constructor
Barcodes(string barcodesFile, string end): m_barcodesFile(barcodesFile), m_end(end) {
initializeBarcodes();
}
// Getters
vector<Barcode> getBCs() {
return m_barcodes;
}
// Other
void initializeBarcodes() {
ifstream flow(m_barcodesFile);
if(!flow) {
cerr << "ERROR: Could'n find the \"barcode.txt\" file." << endl;
}
else {
string line, name, seq;
// parse each line of the barcode file
while(getline(flow, line)) {
//get the name and sequence of the barcodes
name = line.substr(0, 4);
seq = line.substr(5, 6);
//create the corresponding Barcode
string fileName = "Demultiplexed_Reads/" + name + "." + m_end + ".fastq";
Barcode bc(name, seq, m_end, fileName);
//add them in the corresponding vector
m_barcodes.push_back(bc);
}
}
}
private:
string m_barcodesFile;
string m_end;
vector<Barcode> m_barcodes;
};
int main(int argc, char* argv[]) {
//Create a new "Demultiplexed_Reads" folder
system("rm -rf Demultiplexed_Reads");
if(mkdir("Demultiplexed_Reads", 0755) != 0) {
cerr << "ERROR: Couldn't create the Demultiplexed folder." << endl;
return 1;
}
else {
// Get the files to demultiplex
string f1 = argv[1];
string f2 = argv[2];
// Generate the vectors of barcodes
Barcodes bcs1("barcodes.txt", "end1");
vector<Barcode> barcodes1(bcs1.getBCs());
Barcodes bcs2("barcodes.txt", "end2");
vector<Barcode> barcodes2(bcs2.getBCs());
// Demultiplex the reads of the end1
Demultiplexer dm1(f1, barcodes1, "end1");
dm1.demultiplex();
cout << "Reads of end1 demultiplexed" << endl;
// Demultiplex the reads of the end2
Demultiplexer dm2(f2, barcodes2, "end2");
dm2.demultiplex();
cout << "Reads of end2 demultiplexed" << endl;
return 0;
}
}
However, I encounter errors that I don't understand about deleted methods when I am trying to compile g++ --std=c++11 myProg.cpp -o myProg:
In file included from /usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h:33:0,
from /usr/include/c++/5/bits/allocator.h:46,
from /usr/include/c++/5/string:41,
from /usr/include/c++/5/bits/locale_classes.h:40,
from /usr/include/c++/5/bits/ios_base.h:41,
from /usr/include/c++/5/ios:42,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from Demultiplex.cpp:1:
/usr/include/c++/5/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Barcode; _Args = {const Barcode&}; _Tp = Barcode]’:
/usr/include/c++/5/bits/alloc_traits.h:530:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = Barcode; _Args = {const Barcode&}; _Tp = Barcode; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<Barcode>]’
/usr/include/c++/5/bits/stl_vector.h:917:30: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Barcode; _Alloc = std::allocator<Barcode>; std::vector<_Tp, _Alloc>::value_type = Barcode]’
Demultiplex.cpp:85:44: required from here
/usr/include/c++/5/ext/new_allocator.h:120:4: error: use of deleted function ‘Barcode::Barcode(const Barcode&)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
Demultiplex.cpp:18:7: note: ‘Barcode::Barcode(const Barcode&)’ is implicitly deleted because the default definition would be ill-formed:
class Barcode {
^
Demultiplex.cpp:18:7: error: use of deleted function ‘std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const std::basic_ofstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’
In file included from Demultiplex.cpp:2:0:
/usr/include/c++/5/fstream:723:7: note: declared here
basic_ofstream(const basic_ofstream&) = delete;
^
In file included from /usr/include/c++/5/vector:62:0,
from Demultiplex.cpp:4:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Barcode; _Args = {const Barcode&}]’:
/usr/include/c++/5/bits/stl_uninitialized.h:75:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const Barcode*, std::vector<Barcode> >; _ForwardIterator = Barcode*; bool _TrivialValueTypes = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:126:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const Barcode*, std::vector<Barcode> >; _ForwardIterator = Barcode*]’
/usr/include/c++/5/bits/stl_uninitialized.h:281:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const Barcode*, std::vector<Barcode> >; _ForwardIterator = Barcode*; _Tp = Barcode]’
/usr/include/c++/5/bits/stl_vector.h:322:31: required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = Barcode; _Alloc = std::allocator<Barcode>]’
Demultiplex.cpp:63:20: required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: use of deleted function ‘Barcode::Barcode(const Barcode&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
Does anybody know what the problem is ?
Thank you so much !
So I found a way to overcome my problem so I just write the solution I used here in case it would be useful for somebody.
Finally, I created a vector of ofstreams in the method that write into output files instead of putting the streams in the objects. I did it just before the loop that reads ans sorts lines from the input file.
As you said, the trick is no to try to copy the stream since it is not possible. But their reference can be moved into the vector. So I used the move function, which is in the standard since C++11:
ofstream ofs(fileName);
ofStreams.push_back(move(ofs));
I worked for me and allowed my program to be way faster than opening a stream and closing it for every line that I need to sort.
Related
i am storing pointer to object in vector(STL). and i am performing some operation based on Account number , i am using lambda function to solve it .
But I am getting some error .
How to fixed it ???
class BankingSystem {
vector <Account *> vobject;
public :
BankingSystem();
void Create_new_Account();
void Account_info();
void Get_All_Account_info();
void Withdraw();
};
void BankingSystem :: Account_info()
{
long int ACC_NUMBER;
cout << "Enter AccountNumber : " <<endl;
cin >> ACC_NUMBER;
vector<Account*> :: iterator mAccount = std::find_if(vobject.begin(), vobject.end(),
[&ACC_NUMBER](const Account& a) {
// acc_number is maybe called something else in
// your Account class.
return a.Acc_holder.Account_number == ACC_NUMBER;
});
if(mAccount != vobject.end())
{
cout << (*mAccount)->Acc_holder.Account_number << endl;
cout << (*mAccount)->Acc_holder.aadharNo << endl;
vobject.erase(mAccount); // not "delete mAccount;"
}
}
This is an error . i am not getting what exactly the error is ? please elaborate it .
In file included from /usr/include/c++/7/bits/stl_algobase.h:71:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from /home/pankaj/BANK/./include/stdheader.h:4,
from /home/pankaj/BANK/src/bankingSystem.cpp:1:
/usr/include/c++/7/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Iter_pred<_Predicate>::operator()(_Iterator) [with _Iterator = __gnu_cxx::__normal_iterator<account**, std::vector<account*> >; _Predicate = BankingSystem::Account_info()::<lambda(Account&)>]’:
/usr/include/c++/7/bits/stl_algo.h:120:14: required from ‘_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<account**, std::vector<account*> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<BankingSystem::Account_info()::<lambda(Account&)> >]’
/usr/include/c++/7/bits/stl_algo.h:161:23: required from ‘_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = __gnu_cxx::__normal_iterator<account**, std::vector<account*> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<BankingSystem::Account_info()::<lambda(Account&)> >]’
/usr/include/c++/7/bits/stl_algo.h:3932:28: required from ‘_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = __gnu_cxx::__normal_iterator<account**, std::vector<account*> >; _Predicate = BankingSystem::Account_info()::<lambda(Account&)>]’
/home/pankaj/BANK/src/bankingSystem.cpp:40:35: required from here
/usr/include/c++/7/bits/predefined_ops.h:283:11: error: no match for call to ‘(BankingSystem::Account_info()::<lambda(Account&)>) (account*&)’
{ return bool(_M_pred(*__it)); }
^~~~~~~~~~~~~~~~~~~~
/home/pankaj/BANK/src/bankingSystem.cpp:36:58: note: candidate: BankingSystem::Account_info()::<lambda(Account&)>
[&ACC_NUMBER](Account& a) {
^
/home/pankaj/BANK/src/bankingSystem.cpp:36:58: note: no known conversion for argument 1 from ‘account*’ to ‘Account& {aka account&}’
Looking at this line of your code:
vector<Account*> :: iterator mAccount = std::find_if(vobject.begin(), vobject.end(),
[&ACC_NUMBER](const Account& a) {
Your lambda should accept an Account *, not an Account, because you are iterating over a std::vector<Account *>.
I have implemented this simple C++11 Blocking Queue that I'd like to test. In order to test it, I initialize the following producer and consumer thread vectors with 10 producers and 10 consumers respectively.
#include <iostream>
#include <random>
#include <thread>
#include <vector>
#include "blockingqueue.h"
int main() {
// create a blocking queue with capacity 3
blocking_queue<int> queue(3);
uniform_int_distribution<> dis(1, 10);
random_device rd;
mt19937 gen(rd());
// create 10 producers
vector<thread> producers(10, thread([&] () {
cout << "attempting to produce a job ..." << endl;
int job = dis(gen);
queue.put(job);
cout << "produced job " << job << endl;
}));
// create 10 consumers
vector<thread> consumers(10, thread([&] () {
cout << "attempting to take a job ..." << endl;
int job = queue.take();
cout << "consumed job " << job << endl;
}));
// wait for all producers to complete
for(auto& thread : producers){
thread.join();
}
// wait for all consumers to complete
for(auto& thread : consumers){
thread.join();
}
return EXIT_SUCCESS;
}
However, I can't get it to compile with the following errors:
g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/cpp11showcase.d" -MT"src/cpp11showcase.o" -o "src/cpp11showcase.o" "../src/cpp11showcase.cpp"
In file included from /usr/include/c++/4.8/vector:62:0,
from ../src/cpp11showcase.cpp:13:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::thread; _Args = {const std::thread&}]’:
/usr/include/c++/4.8/bits/stl_uninitialized.h:187:48: required from ‘static void std::__uninitialized_fill_n<_TrivialValueType>::__uninit_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = std::thread*; _Size = long unsigned int; _Tp = std::thread; bool _TrivialValueType = false]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:224:35: required from ‘void std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = std::thread*; _Size = long unsigned int; _Tp = std::thread]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:334:50: required from ‘void std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, std::allocator<_Tp2>&) [with _ForwardIterator = std::thread*; _Size = long unsigned int; _Tp = std::thread; _Tp2 = std::thread]’
/usr/include/c++/4.8/bits/stl_vector.h:1215:32: required from ‘void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = std::thread; _Alloc = std::allocator<std::thread>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::thread]’
/usr/include/c++/4.8/bits/stl_vector.h:284:40: required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::thread; _Alloc = std::allocator<std::thread>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::thread; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::thread>]’
../src/cpp11showcase.cpp:83:4: required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘std::thread::thread(const std::thread&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
In file included from ../src/blockingqueue.h:13:0,
from ../src/cpp11showcase.cpp:18:
/usr/include/c++/4.8/thread:126:5: error: declared here
thread(const thread&) = delete;
^
make: *** [src/cpp11showcase.o] Error 1
UPDATE: it seems that the vector initialization doesn't like to capture the referenced variables by reference i.e. queue, dis and gen. The thread copy constructor has the method thread(const thread&) = delete; unavailable
// create 10 producers
vector<thread> producers(10, thread([&] () {
cout << "attempting to produce a job ..." << endl;
int job = dis(gen);
queue.put(job);
cout << "produced job " << job << endl;
}));
The constructor of std::vector will copy the std::thread 10 times, but you can't copy a std::thread, because its copy constructor is deleted.
Instead, you can use std::vector::emplace_back:
vector<thread> producers;
//Loop 10 times (for 10 threads)
for (std::size_t i = 0; i < 10; ++i)
produces.emplace_back([&] () {
cout << "attempting to take a job ..." << endl;
int job = queue.take();
cout << "consumed job " << job << endl;
});
I don't think there is a way to construct n elements in place in a std::vector, but you could put the loop in a function:
template<typename T>
void fillThread(std::vector<std::thread>& threads, std::size_t count, T func)
{
for (std::size_t i = 0; i < count; ++i)
threads.emplace_back(func);
}
You can then call it like so:
std::vector<std::thread> producers;
fillThread(producers, 10, [&] () {
cout << "attempting to take a job ..." << endl;
int job = queue.take();
cout << "consumed job " << job << endl;
});
I am trying to implement BFS in C++, Here is the code.
#include <iostream>
#include <list>
#include <string>
#include <limits>
#include <map>
int infinity=std::numeric_limits<int>::max();
struct Node{
int value;
int distance;
std::string color;
Node(int val):
value(val),
distance(infinity),
color("white")
{}
};
//using AdjList = std::map<Node*,std::list<Node*>>;
typedef std::map<Node*,std::list<Node*>> AdjList;
AdjList create_graph()
{
Node* n1 = new Node(1);
Node* n2 = new Node(2);
Node* n3 = new Node(3);
Node* n4 = new Node(4);
Node* n5 = new Node(5);
Node* n6 = new Node(6);
Node* n7 = new Node(7);
Node* n8 = new Node(8);
AdjList m;
m[n1] = {n2, n5};
m[n2] = {n1, n6};
m[n3] = {n4, n6, n7};
m[n4] = {n3, n7, n8};
m[n5] = {n1};
m[n6] = {n2, n3, n7};
m[n7] = {n3, n4, n6, n8};
m[n8] = {n4, n7};
return m;
}
void bfs(const AdjList& m, Node* n1)
{
std::list<Node*> queue;
queue.push_back(n1);
unsigned count = 0;
while (!queue.empty())
{
auto n = queue.front();
std::cout << n->value << std::endl;
queue.pop_front();
std::cout << *(m[n].begin()) << std::endl;
for(auto it = m[n].begin(); it != m[n].end(); ++it)
{
if ((*it)->color != "black")
queue.push_back(*it);
}
n->color = "black";
n->distance = count;
++count;
}
}
On trying to compile with gcc, I receive the following error messages.
bfs.cpp: In function ‘void bfs(const AdjList&, Node*)’:
bfs.cpp:59:27: error: passing ‘const AdjList {aka const std::map<Node*, std::list<Node*> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = Node*; _Tp = std::list<Node*>; _Compare = std::less<Node*>; _Alloc = std::allocator<std::pair<Node* const, std::list<Node*> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::list<Node*>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = Node*]’ discards qualifiers [-fpermissive]
std::cout << *(m[n].begin()) << std::endl;
^
bfs.cpp:60:20: error: passing ‘const AdjList {aka const std::map<Node*, std::list<Node*> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = Node*; _Tp = std::list<Node*>; _Compare = std::less<Node*>; _Alloc = std::allocator<std::pair<Node* const, std::list<Node*> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::list<Node*>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = Node*]’ discards qualifiers [-fpermissive]
for(auto it = m[n].begin(); it != m[n].end(); ++it)
^
bfs.cpp:60:40: error: passing ‘const AdjList {aka const std::map<Node*, std::list<Node*> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = Node*; _Tp = std::list<Node*>; _Compare = std::less<Node*>; _Alloc = std::allocator<std::pair<Node* const, std::list<Node*> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::list<Node*>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = Node*]’ discards qualifiers [-fpermissive]
for(auto it = m[n].begin(); it != m[n].end(); ++it)
I am not sure what is wrong. Please point out the mistake.
std::map::operator[] is non-const because it will insert elements if needed:
int main()
{
std::map<std::string, std::string> m;
m["new element"] = "1";
}
The problem is that m is a const AdjList&, on which you cannot call non-const member functions. You can use std::map::find() instead:
auto itor = m.find(n);
if (itor != m.end())
std::cout << *(m->second.begin()) << std::endl;
Two C++11 features will make your life much easier
the at() const function for maps, which is like [] but throws an out of range exception if the key is not there, instead of adding a new item to the map.
the for loop over containers
So :
for (auto it : m.at(n)) {
if (it->color != "black")
queue.push_back(it);
}
I'm having a bit of trouble understanding what's happening when I try to delete an element from a list in this program i'm working on.
#include <cmath>
#include <cstdio>
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int findHigherSkillLevel(int skillLevel, list<int>::iterator *it, list<int> &list) {
if (it == NULL) return 0;
if (**it == (skillLevel + 1)) {
it = list.erase(it);
return 1 + findHigherSkillLevel(**it, it, list) + findHigherSkillLevel(**it, --it, list);
}
return 0;
}
int findLowerSkillLevel(int skillLevel, list<int>::iterator *it, list<int> &list) {
if (it == NULL) return 0;
if (**it == (skillLevel - 1)) {
it = list.erase(it);
return 1 + findLowerSkillLevel(**it, it, list) + findLowerSkillLevel(**it, --it, list);
}
return 0;
}
int findGroupsSizes(int skillLevel, list<int>::iterator *it, list<int> &list) {
if (it == NULL) return 0;
int groupSize = 1;
it = list.erase(it);
groupSize += findHigherSkillLevel(**it, it, list) + findLowerSkillLevel(**it, it, list);
return groupSize;
}
int main() {
int t; // the number of test cases
cin >> t;
vector<list<int> > skillLevels(t, list<int>());
// input for each test case
for (int i = 0; i < t; i++) {
int n; // number of students for this test case
cin >> n;
// initialize the list for this test case
for (int j = 0; j < n; j++) {
int skillLevel;
cin >> skillLevel;
skillLevels[i].push_back(skillLevel);
}
}
// recursively scan lists for smallest teams
for (int i = 0; i < t; i++) {
int minGroupNumber = skillLevels[i].size();
list<int>::iterator iterator = skillLevels[i].begin();
int skillLevel = skillLevels[i].front();
while (!skillLevels[i].empty()) {
int currentGroupSize = findGroupsSizes(skillLevel, &iterator, skillLevels[i]);
if (currentGroupSize < minGroupNumber)
minGroupNumber = currentGroupSize;
skillLevels[i].pop_front();
}
cout << minGroupNumber << endl;
}
return 0;
}
I already know that what's causing the error trying to call the "erase" function like this:
it = list.erase(it);
Which I typed in bold in the code. I don't understand why it's giving me the following output, since from what I understand erase() just needs an iterator to the location of the list to be deleted?:
teamFormation.cpp: In function ‘int findHigherSkillLevel(int, std::list<int>::iterator*, std::list<int>&)’:
teamFormation.cpp:13:24: error: no matching function for call to ‘std::list<int>::erase(std::list<int>::iterator*&)’
it = *list.erase(it);
^
teamFormation.cpp:13:24: note: candidates are:
In file included from /usr/include/c++/4.8/list:64:0,
from teamFormation.cpp:3:
/usr/include/c++/4.8/bits/list.tcc:108:5: note: std::list<_Tp, _Alloc>::iterator std::list<_Tp, _Alloc>::erase(std::list<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<int>]
list<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/list.tcc:108:5: note: no known conversion for argument 1 from ‘std::list<int>::iterator* {aka std::_List_iterator<int>*}’ to ‘std::list<int>::iterator {aka std::_List_iterator<int>}’
In file included from /usr/include/c++/4.8/list:63:0,
from teamFormation.cpp:3:
/usr/include/c++/4.8/bits/stl_list.h:1193:7: note: std::list<_Tp, _Alloc>::iterator std::list<_Tp, _Alloc>::erase(std::list<_Tp, _Alloc>::iterator, std::list<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<int>]
erase(iterator __first, iterator __last)
^
/usr/include/c++/4.8/bits/stl_list.h:1193:7: note: candidate expects 2 arguments, 1 provided
teamFormation.cpp: In function ‘int findLowerSkillLevel(int, std::list<int>::iterator*, std::list<int>&)’:
teamFormation.cpp:24:24: error: no matching function for call to ‘std::list<int>::erase(std::list<int>::iterator*&)’
it = *list.erase(it);
^
teamFormation.cpp:24:24: note: candidates are:
In file included from /usr/include/c++/4.8/list:64:0,
from teamFormation.cpp:3:
/usr/include/c++/4.8/bits/list.tcc:108:5: note: std::list<_Tp, _Alloc>::iterator std::list<_Tp, _Alloc>::erase(std::list<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<int>]
list<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/list.tcc:108:5: note: no known conversion for argument 1 from ‘std::list<int>::iterator* {aka std::_List_iterator<int>*}’ to ‘std::list<int>::iterator {aka std::_List_iterator<int>}’
In file included from /usr/include/c++/4.8/list:63:0,
from teamFormation.cpp:3:
/usr/include/c++/4.8/bits/stl_list.h:1193:7: note: std::list<_Tp, _Alloc>::iterator std::list<_Tp, _Alloc>::erase(std::list<_Tp, _Alloc>::iterator, std::list<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<int>]
erase(iterator __first, iterator __last)
^
/usr/include/c++/4.8/bits/stl_list.h:1193:7: note: candidate expects 2 arguments, 1 provided
teamFormation.cpp: In function ‘int findGroupsSizes(int, std::list<int>::iterator*, std::list<int>&)’:
teamFormation.cpp:35:22: error: no matching function for call to ‘std::list<int>::erase(std::list<int>::iterator*&)’
it = *list.erase(it);
^
teamFormation.cpp:35:22: note: candidates are:
In file included from /usr/include/c++/4.8/list:64:0,
from teamFormation.cpp:3:
/usr/include/c++/4.8/bits/list.tcc:108:5: note: std::list<_Tp, _Alloc>::iterator std::list<_Tp, _Alloc>::erase(std::list<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<int>]
list<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/list.tcc:108:5: note: no known conversion for argument 1 from ‘std::list<int>::iterator* {aka std::_List_iterator<int>*}’ to ‘std::list<int>::iterator {aka std::_List_iterator<int>}’
In file included from /usr/include/c++/4.8/list:63:0,
from teamFormation.cpp:3:
/usr/include/c++/4.8/bits/stl_list.h:1193:7: note: std::list<_Tp, _Alloc>::iterator std::list<_Tp, _Alloc>::erase(std::list<_Tp, _Alloc>::iterator, std::list<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::list<_Tp, _Alloc>::iterator = std::_List_iterator<int>]
erase(iterator __first, iterator __last)
^
/usr/include/c++/4.8/bits/stl_list.h:1193:7: note: candidate expects 2 arguments, 1 provided
The error message is self-explanatory: at that point it is not a std::list::iterator, it's actually an std::list::iterator*. You must dereference the pointer (as you did just on the previous line).
I have a data array with 2*N ints, representing pairs, that is for even i=0,2,4,...,2*N (pairs[i], pairs[i+1]) is such a pair. The data is formatted like this because I use Matlab's mex library. I do:
int N=5;
int data[10] = {1,2,3,4,5,6,7,8,9,10};
struct Pair { int first; int second; };
Pair * pairs = (Pair *)data;
but the problem would be that there is no way to guarantee that Pair aligns as two sizeof(ints) in order first, second. See: Is the member field order of a class "stable"?
I don't want to process and copy all data into a new array, since it should not be necessary, and I need (as far as I can see) to use
typedef int Pair[2];
to be sure that it aligns correctly (no trailing garbage bytes, etc). if I then want to sort the pairs according to the first element, I could do:
#include <iostream>
#include <algorithm>
typedef int Pair[2];
int compare(Pair n1, Pair n2) { return n1[0] < n2[0]; }
int main() {
int N=5;
int data[10] = {1,2, 7,8, 13,14, 4,5, 10,11};
Pair *pairs = (Pair *)((void *)data);
std::cout << "unsorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
std::sort(data, data+N, compare);
std::cout << "sorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
return 0;
}
see: http://ideone.com/VyBUvc
I could summarize the error message as error: array must be initialized with a brace-enclosed initializer, see below for the complete message. It is caused by the std::sort call.
I wrapped the Pair typedef in a union here ( http://ideone.com/TVmEeZ ), and that seems to work. Why does c++ (or std::sort) not see int[2] in a similar way as a union?
Complete compiler output:
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
from /usr/include/c++/4.8/bits/stl_algobase.h:64,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from prog.cpp:1:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:2250:70: required from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5514:55: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_algo.h:2186:11: error: array must be initialized with a brace-enclosed initializer
__val = _GLIBCXX_MOVE(*__i);
^
In file included from /usr/include/c++/4.8/algorithm:62:0,
from prog.cpp:2:
/usr/include/c++/4.8/bits/stl_algo.h:2188:17: error: invalid array assignment
*__first = _GLIBCXX_MOVE(__val);
^
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&, _Compare) [with _RandomAccessIterator = int (*)[2]; _Tp = int [2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:2319:78: required from ‘_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2360:62: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_algo.h:2287:35: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
while (__comp(*__first, __pivot))
^
/usr/include/c++/4.8/bits/stl_algo.h:2290:34: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
while (__comp(__pivot, *__last))
^
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
from /usr/include/c++/4.8/bits/stl_algobase.h:64,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from prog.cpp:1:
/usr/include/c++/4.8/bits/stl_heap.h: In instantiation of ‘void std::make_heap(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:1970:47: required from ‘void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5363:59: required from ‘void std::partial_sort(_RAIter, _RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2355:68: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_heap.h:446:25: error: array must be initialized with a brace-enclosed initializer
_ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
^
/usr/include/c++/4.8/bits/stl_heap.h: In instantiation of ‘void std::__pop_heap(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:1973:50: required from ‘void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5363:59: required from ‘void std::partial_sort(_RAIter, _RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2355:68: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_heap.h:339:28: error: array must be initialized with a brace-enclosed initializer
_ValueType __value = _GLIBCXX_MOVE(*__result);
^
In file included from /usr/include/c++/4.8/bits/stl_algo.h:61:0,
from /usr/include/c++/4.8/algorithm:62,
from prog.cpp:2:
/usr/include/c++/4.8/bits/stl_heap.h:340:17: error: invalid array assignment
*__result = _GLIBCXX_MOVE(*__first);
^
std::sort(data, data+N, compare);
You are sorting data, not pairs. That said, your new approach is still undefined behaviour, and thus not guaranteed to work1. You are essentially trying to fit a square peg into a round hole. If you want to use std::sort, present valid data – which means copying in your case, or writing a custom iterator which treats an array as a collection of consecutive pairs.
1 That’s a humungous understatement. – Do not do this.
Exchanging your array of two int for a std::pair<int,int> did the trick for me (live at ideone):
#include <iostream>
#include <algorithm>
#include <memory>
typedef std::pair<int,int> Pair;
bool compare(const Pair& i, const Pair& j) { return i.first < j.first; }
int main() {
const int N=5;
Pair pairs[N] = {{1,2}, {7,8}, {13,14}, {4,5}, {10,11}};
std::cout << "unsorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i].first << ", " << pairs[i].second << ")" << std::endl;
std::sort(pairs, pairs+N, compare);
std::cout << "sorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i].first << ", " << pairs[i].second << ")" << std::endl;
}
An alternative would be encapsulating the array of two int inside a struct. The problem in your code is that std::sort need an array of comparable (you fixed it with your compare function) and copy-or-move-assignable items (arrays are neither)
Maybe even better (less changes to your code) would be using std::array:
#include <iostream>
#include <algorithm>
#include <memory>
typedef std::array<int, 2> Pair;
bool compare(const Pair& i, const Pair& j) { return i[0] < j[0]; }
int main() {
const int N=5;
Pair pairs[N] = {1,2, 7,8, 13,14, 4,5, 10,11};
std::cout << "unsorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
std::sort(pairs, pairs+N, compare);
std::cout << "sorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
}