STL algorithm cannot access private member - c++
Apologize in advance for the amount of codes, but I can't find where the built error coming from. This example built correctly on VC++ 6.0, but failed on the more recent compilers, including g++ and VC++ 2010. The error message says error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>' Help please.
#pragma warning( disable : 4786 )
#pragma warning( disable : 4996 )
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <list>
#include <numeric>
#include <iterator>
template<class T>
class Criteria {
public:
Criteria(T match) : m_match(match) {
}
bool operator()(T match) {
return (m_match == match);
}
private:
T m_match;
};
template<class T>
class BinaryCriteria {
public:
bool operator()(T item1, T item2) {
return (item1*item1 > item2+item2);
}
};
std::ostream& operator<<(std::ostream& o, std::string rhs) {
return (o << rhs.c_str());
}
void print( int x ) {
std::cout << x << " ";
}
template<class T>
class Print {
public:
Print(const char* sep) : m_sep(sep) {
}
void operator()(T item) {
std::cout << item << m_sep.c_str();
}
private:
std::string m_sep;
};
template<class T>
class Equal {
public:
bool operator()(T item1, T item2) {
return (item1 * 2 == item2);
}
};
template<class T>
class File {
public:
File(const char* file) {
m_in.open(file);
}
~File() {
if (m_in)
m_in.close();
}
T operator()() {
m_in.getline(m_buf, sizeof(m_buf));
T line = m_buf;
return line;
}
private:
std::ifstream m_in;
char m_buf[80];
};
template<class T>
class Odd {
public:
bool operator()(T item) {
if (item % 2 != 0)
return false;
else
return true;
}
};
template<class T>
class Upper {
public:
T operator()(T item) {
std::transform(item.begin(),item.end(),item.begin(),::toupper);
return item;
}
};
template<class T>
class Concat {
public:
Concat(const char* sep) : m_sep(sep) {
}
T operator()(T item1, T item2) {
T out;
out = item1;
out += m_sep;
out += item2;
return out;
}
private:
std::string m_sep;
};
template<class T>
class TheSame {
public:
bool operator()(T item1, T item2) {
if (item1 * 10 == item2)
return true;
else
return false;
}
};
template<class T>
class Rand {
public:
T operator()() {
return static_cast<T>(::rand());
}
};
struct Employee {
Employee(std::string name, std::string dept, std::string id) :
m_name(name), m_dept(dept), m_id(id) {
}
std::string m_name;
std::string m_dept;
std::string m_id;
};
class SortByName {
public:
bool operator()(const Employee* lhs, const Employee* rhs) {
int res = ::strcmp(lhs->m_name.c_str(),rhs->m_name.c_str());
if (res == -1)
return true;
else
return false;
}
};
class SortByDept {
public:
bool operator()(const Employee* lhs, const Employee* rhs) {
int res = ::strcmp(lhs->m_dept.c_str(),rhs->m_dept.c_str());
if (res == -1)
return true;
else
return false;
}
};
class SortById {
public:
bool operator()(const Employee* lhs, const Employee* rhs) {
int res = ::strcmp(lhs->m_id.c_str(),rhs->m_id.c_str());
if (res == -1)
return true;
else
return false;
}
};
std::ostream& operator<<(std::ostream& o, const Employee* rhs) {
o << rhs->m_name << "," << rhs->m_dept << "," << rhs->m_id;
return o;
}
int main(int argc, char* argv[]) {
if (false) {
std::vector<int> v;
for (int i=0; i<10; i++)
v.push_back(i);
std::vector<int>::iterator ifind = std::find(v.begin(), v.end(), -4);
if (ifind != v.end())
std::cout << "Item found " << *ifind << std::endl;
else
std::cout << "Item was not found" << std::endl;
ifind = std::find_if(v.begin(), v.end(), Criteria<int>(4));
if (ifind != v.end())
std::cout << "Item found " << *ifind << std::endl;
else
std::cout << "Item was not found" << std::endl;
}
if (false) {
std::vector<int> v;
for (int i=0; i<10; i++)
v.push_back(i);
v[4] = 5; // create an adjacent pair
std::vector<int>::iterator ifind = std::adjacent_find(v.begin(), v.end());
if (ifind != v.end())
std::cout << "Items found " << *ifind << " " << *(ifind+1) << std::endl;
else
std::cout << "Items were not found" << std::endl;
v[4] = 4; // create an adjacent pair
ifind = std::adjacent_find(v.begin(), v.end(), BinaryCriteria<int>());
if (ifind != v.end())
std::cout << "Items found " << *ifind << " " << *(ifind+1) << std::endl;
else
std::cout << "Items were not found" << std::endl;
}
if (false) {
std::vector<int> v;
for (int i=0; i<10; i++)
v.push_back(i);
v[3] = 3;
v[7] = 3; // some duplicates
std::cout << "The item " << 2 << " appears "
<< std::count( v.begin(), v.end(), 2)
<< " times" << std::endl;
std::cout << "The item " << 3 << " appears "
<< std::count_if( v.begin(), v.end(), Criteria<int>(3))
<< " times" << std::endl;
}
if (false) {
std::vector<int> v;
for (int i=0; i<10; i++)
v.push_back(i);
std::for_each(v.begin(), v.end(), Print<int>(" "));
std::cout << std::endl;
std::for_each(v.begin(), v.end(), print);
std::cout << std::endl;
}
if (false) {
std::vector<int> v;
for (int i=0; i<10; i++)
v.push_back(i);
int tab[3] = { 0, 1, 2 };
bool res = std::equal(tab, tab+3, v.begin());
if (res)
std::cout << "Ranges are equal" << std::endl;
else
std::cout << "Ranges are not equal" << std::endl;
v[0] = 2 * tab[0];
v[1] = 2 * tab[1];
v[2] = 2 * tab[2];
res = std::equal(tab, tab+3, v.begin(), Equal<int>());
if (res)
std::cout << "Ranges are equal" << std::endl;
else
std::cout << "Ranges are not equal" << std::endl;
res = std::equal(tab, tab+3, v.begin());
if (res)
std::cout << "Ranges are equal" << std::endl;
else
std::cout << "Ranges are not equal" << std::endl;
res = std::equal(tab, tab+3, &v[5], Equal<int>());
if (res)
std::cout << "Ranges are equal" << std::endl;
else
std::cout << "Ranges are not equal" << std::endl;
}
if (false) {
std::vector<int> v;
for (int i=0; i<10; i++)
v.push_back(i);
int tab[6] = { 0, 1, 2, 4, 5, 6 };
std::pair<int*, std::vector<int>::iterator> res =
std::mismatch(tab, tab+6, v.begin() );
if (res.first != (tab+6)) {
std::cout << "mismatch located "
<< "item in first range " << *res.first <<
" item in second range " << *res.second << std::endl;
} else
std::cout << "No mismatch found within the range" << std::endl;
v[0] = 2 * tab[0];
v[1] = 2 * tab[1];
v[2] = 2 * tab[2];
tab[3] = -99;
res = std::mismatch(tab, tab+6, v.begin(), Equal<int>() );
if (res.first != (tab+6)) {
std::cout << "mismatch located "
<< "item in first range " << *res.first <<
" item in second range " << *res.second << std::endl;
} else
std::cout << "No mismatch found within the range" << std::endl;
}
if (false) {
std::vector<int> v;
for (int i=0; i<10; i++)
v.push_back(i);
int tab[3] = { 4, 5, 6 };
std::vector<int>::iterator res = std::search(v.begin(), v.end(), tab, tab+3);
if (res != v.end())
std::cout << "Subsequence located - first item = " << *res << std::endl;
else
std::cout << "Subsequence not located" << std::endl;
tab[0] = 2 * v[5];
tab[1] = 2 * v[6];
tab[2] = 2 * v[7];
// predicate function version
res = std::search(v.begin(), v.end(), tab, tab+3, Equal<int>());
if (res != v.end())
std::cout << "Subsequence located - first item = " << *res << std::endl;
else
std::cout << "Subsequence not located" << std::endl;
}
if (false) {
std::vector<int> v(10);
int tab[10] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
std::copy(tab,tab+10,v.begin());
std::for_each(v.begin(),v.end(),Print<int>(" "));
std::cout << std::endl;
std::copy_backward(tab,tab+10,v.end());
std::for_each(v.begin(),v.end(),Print<int>(" "));
std::cout << std::endl;
std::vector<char> v2;
const char* str = "ABCDEFGHIJ";
std::copy(str,str+10,std::back_inserter(v2));
std::cout << "Before shift left" << std::endl;
std::for_each(v2.begin(),v2.end(),Print<char>(""));
std::cout << std::endl;
std::copy(v2.begin()+1, v2.end(), v2.begin());
std::cout << "After shift left" << std::endl;
std::for_each(v2.begin(),v2.end(),Print<char>(""));
std::cout << std::endl;
std::copy(str,str+10,v2.begin());
std::cout << "Before shift right" << std::endl;
std::for_each(v2.begin(),v2.end(),Print<char>(""));
std::cout << std::endl;
std::copy_backward(v2.begin(), v2.end()-1, v2.end());
std::cout << "After shift right" << std::endl;
std::for_each(v2.begin(),v2.end(),Print<char>(""));
std::cout << std::endl;
}
if (false) {
std::vector<int> v(10);
std::fill(v.begin(),v.end(),-5);
std::for_each(v.begin(),v.end(),Print<int>(" "));
std::cout << std::endl;
std::fill_n(v.begin(),10,-5);
std::for_each(v.begin(),v.end(),Print<int>(" "));
std::cout << std::endl;
}
if (false) {
std::vector<std::string> v(10);
std::generate(v.begin(),v.end(),File<std::string>("c:/temp/items.txt"));
std::for_each(v.begin(),v.end(),Print<std::string>("\n"));
std::cout << std::endl;
}
if (false) {
std::vector<int> v;
for(int i=0; i<10; i++)
v.push_back(i);
std::vector<int>::iterator res =
std::partition(v.begin(),v.end(),Odd<int>());
// display each range
std::cout << "first range ";
std::for_each(v.begin(),res,Print<int>(" "));
std::cout << std::endl;
std::cout << "second range ";
std::for_each(res,v.end(),Print<int>(" "));
std::cout << std::endl;
// repeat for stable_partition
for(int i=0; i<10; i++)
v[i]=i;
res = std::stable_partition(v.begin(),v.end(),Odd<int>());
// display each range
std::cout << "first range ";
std::for_each(v.begin(),res,Print<int>(" "));
std::cout << std::endl;
std::cout << "second range ";
std::for_each(res,v.end(),Print<int>(" "));
std::cout << std::endl;
// repeat using STL components
for(int i=0; i<10; i++)
v[i]=i;
res = std::partition(v.begin(),v.end(),
std::bind2nd( std::greater<int>(), 2));
// display each range
std::cout << "first range ";
std::for_each(v.begin(),res,Print<int>(" "));
std::cout << std::endl;
std::cout << "second range ";
std::for_each(res,v.end(),Print<int>(" "));
std::cout << std::endl;
// repeat using STL components
for(int i=0; i<10; i++)
v[i]=i;
res = std::partition(v.begin(),v.end(),
std::bind1st( std::greater<int>(), 2));
// display each range
std::cout << "first range ";
std::for_each(v.begin(),res,Print<int>(" "));
std::cout << std::endl;
std::cout << "second range ";
std::for_each(res,v.end(),Print<int>(" "));
std::cout << std::endl;
}
if (false) {
// random_shuffle randomly rearranges the items in a range.
std::vector<int> v;
for(int i=0; i<100; i++)
v.push_back(i);
std::random_shuffle(v.begin(),v.end());
std::copy(v.begin(),v.end(),
std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
}
if (false) {
int buf[10] = { 2, 5, 3, 5, 4, 5, 6, 6, 5, 5 };
int* res = std::remove(buf, buf+10, 5);
std::cout << "items to keep ";
std::copy(buf, res, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::cout << "items to remove ";
std::copy(res, buf+10, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
// test with vector
std::vector<int> v;
for(int i=0; i<10; i++)
v.push_back(i);
std::cout << "size of v before call to remove " << v.size() << std::endl;
std::vector<int>::iterator p = std::remove(v.begin(), v.end(), 5);
std::cout << "size of v after call to remove " << v.size() << std::endl;
v.erase(p);
std::cout << "size of v after erase " << v.size() << std::endl;
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
}
if (false) {
int buf[10] = { 2, 5, 3, 5, 4, 5, 6, 6, 5, 5 };
std::copy(buf, buf+10, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::replace(buf, buf+10, 5, 0);
std::copy(buf, buf+10, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
}
if (false) {
// The reverse algorithm reverses the order of the items in a given range.
int buf[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << "Before reverse ";
std::copy(buf, buf+10, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::reverse(buf, buf+10);
std::cout << "After reverse ";
std::copy(buf, buf+10, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
}
if (false) {
int buf[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << "Before rotate ";
std::copy(buf, buf+10, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
std::rotate(buf, buf+4, buf+10);
std::cout << "After rotate ";
std::copy(buf, buf+10, std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
}
if (false) {
// The swap function swaps to values
std::string first="Hello";
std::string second="World";
std::cout << first << " " << second << std::endl;
std::swap(first,second);
std::cout << first << " " << second << std::endl;
// The swap_ranges function swaps ranges.
std::list<std::string> ll;
ll.push_front("Homer");
ll.push_front("Marge");
ll.push_front("Bart");
std::vector<std::string> vec;
vec.push_back("Moe");
vec.push_back("Wiggum");
vec.push_back("Burns");
std::swap_ranges(ll.begin(),ll.end(),vec.begin());
std::cout << "List values ";
std::for_each(ll.begin(),ll.end(),Print<std::string>(" "));
std::cout << std::endl;
std::cout << "Vector values ";
std::for_each(vec.begin(),vec.end(),Print<std::string>(" "));
std::cout << std::endl;
}
if (false) {
std::vector<std::string> v(3);
std::list<std::string> ll;
ll.push_front("Homer");
ll.push_front("Marge");
ll.push_front("Bart");
std::transform(ll.begin(),ll.end(),v.begin(),Upper<std::string>());
std::cout << "Uppercase names ";
std::for_each(v.begin(),v.end(),Print<std::string>(" "));
std::cout << std::endl;
std::list<std::string> ll2;
ll2.push_front("Simpson");
ll2.push_front("Simpson");
ll2.push_front("Simpson");
std::transform(ll.begin(),ll.end(),ll2.begin(),v.begin(),Concat<std::string>(" "));
std::cout << "Concat'ed names ";
std::for_each(v.begin(),v.end(),Print<std::string>("\n"));
std::cout << std::endl;
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int b[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int c[10];
std::transform(a,a+10,b,c,std::plus<int>());
std::for_each(c,c+10,Print<int>(" "));
std::cout << std::endl;
std::transform(a,a+10,c,std::bind2nd(std::plus<int>(),10));
std::for_each(c,c+10,Print<int>(" "));
std::cout << std::endl;
}
if (false) {
int tab[10] = { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7 };
int* res = std::unique(tab, tab+10);
std::cout << "Unique items ";
std::for_each(tab,res,Print<int>(" "));
std::cout << std::endl;
// Binary predicate function version.
int tab2[10] = { 1, 2, 20, 3, 4, 40, 5, 6, 60, 7 };
res = std::unique(tab2, tab2+10, TheSame<int>());
std::cout << "Unique items ";
std::for_each(tab2,res,Print<int>(" "));
std::cout << std::endl;
int tab3[10] = { 1, 2, 20, 3, 4, 40, 5, 6, 60, 7 };
res = std::unique(tab3, tab3+10);
std::cout << "Unique items ";
std::for_each(tab3,res,Print<int>(" "));
std::cout << std::endl;
}
if (false) {
int tab[10];
// initialize
std::generate(tab,tab+10,Rand<int>());
std::cout << "Unsorted sequence ";
std::for_each(tab,tab+10,Print<int>(" "));
std::cout << std::endl;
std::sort(tab,tab+10,std::less<int>());
std::cout << "Sorted ascending order sequence ";
std::for_each(tab,tab+10,Print<int>(" "));
std::cout << std::endl;
// initialize
std::generate(tab,tab+10,Rand<int>());
std::cout << "Unsorted sequence ";
std::for_each(tab,tab+10,Print<int>(" "));
std::cout << std::endl;
std::sort(tab,tab+10,std::greater<int>());
std::cout << "Sorted descending order sequence ";
std::for_each(tab,tab+10,Print<int>(" "));
std::cout << std::endl;
// customize the sort criteria
std::vector<Employee*> v;
v.push_back( new Employee("EEE", "Dept AAA", "Id100") );
v.push_back( new Employee("CCC", "Dept BBB", "Id500") );
v.push_back( new Employee("BBB", "Dept DDD", "Id300") );
v.push_back( new Employee("FFF", "Dept CCC", "Id600") );
v.push_back( new Employee("AAA", "Dept CCC", "Id200") );
v.push_back( new Employee("DDD", "Dept AAA", "Id000") );
std::cout << "Unsorted employees " << std::endl;
std::for_each(v.begin(),v.end(),Print<Employee*>("\n"));
std::cout << std::endl;
// sort by name
std::sort(v.begin(),v.end(),SortByName());
std::cout << "Sorted employees by name " << std::endl;
std::for_each(v.begin(),v.end(),Print<Employee*>("\n"));
std::cout << std::endl;
// sort by id
std::sort(v.begin(),v.end(),SortById());
std::cout << "Sorted employees by id " << std::endl;
std::for_each(v.begin(),v.end(),Print<Employee*>("\n"));
std::cout << std::endl;
// sort by dept
std::sort(v.begin(),v.end(),SortByDept());
std::cout << "Sorted employees by dept " << std::endl;
std::for_each(v.begin(),v.end(),Print<Employee*>("\n"));
std::cout << std::endl;
// sort by name, the by dept
std::sort(v.begin(),v.end(),SortByName());
std::stable_sort(v.begin(),v.end(),SortByDept());
std::cout << "Sorted employees by name then stable sorted by dept " << std::endl;
std::for_each(v.begin(),v.end(),Print<Employee*>("\n"));
std::cout << std::endl;
// initialize
std::generate(tab,tab+10,Rand<int>());
std::cout << "Unsorted sequence " << std::endl;
std::for_each(tab,tab+10,Print<int>(" "));
std::cout << std::endl;
std::partial_sort(tab,tab+3,tab+10,std::greater<int>());
std::cout << "Partially sorted (top 3) in descending order sequence " << std::endl;
std::for_each(tab,tab+10,Print<int>(" "));
std::cout << std::endl;
double salaries[10] = { 22000.0, 28500.00, 17500.00, 22000.0, 54000.00,
77500.00, 18400.00, 100000.00, 23000.0, 50000.0 };
std::nth_element(salaries, salaries+2, salaries+10, std::less<double>());
std::cout << "The 3rd top salary is " << salaries[2] << std::endl;
std::cout << std::endl;
}
if (false) {
std::vector<int> keys;
for (int i=0; i<100; i++)
keys.push_back(i);
std::sort(keys.begin(), keys.end(), std::less<int>());
// is item 55 in the sequence?
bool isThere = std::binary_search(keys.begin(), keys.end(), int(55));
if (isThere)
std::cout << "The key 55 is in the sequence" << std::endl;
else
std::cout << "The key 55 is not in the sequence" << std::endl;
// is item 555 in the sequence?
isThere = std::binary_search(keys.begin(), keys.end(), int(555));
if (isThere)
std::cout << "The key 555 is in the sequence" << std::endl;
else
std::cout << "The key 555 is not in the sequence" << std::endl;
}
if (false) {
std::list<float> ll;
ll.push_front(70.0f);
ll.push_front(60.0f);
ll.push_front(50.0f);
ll.push_front(30.0f);
ll.push_front(20.0f);
ll.push_front(10.0f);
std::list<float>::iterator iter =
std::lower_bound(ll.begin(), ll.end(), 40.0f);
ll.insert(iter, 40.0f);
std::for_each(ll.begin(), ll.end(), Print<float>(" "));
std::cout << std::endl;
std::list<float> ll2;
ll2.push_front(70.0f);
ll2.push_front(60.0f);
ll2.push_front(50.0f);
ll2.push_front(30.0f);
ll2.push_front(20.0f);
ll2.push_front(10.0f);
std::list<float>::iterator iter2 =
std::upper_bound(ll2.begin(), ll2.end(), 40.0f);
ll2.insert(iter2, 40.0f);
std::for_each(ll2.begin(), ll2.end(), Print<float>(" "));
std::cout << std::endl;
std::list<float> ll3;
ll3.push_front(70.0f);
ll3.push_front(60.0f);
ll3.push_front(50.0f);
ll3.push_front(30.0f);
ll3.push_front(20.0f);
ll3.push_front(10.0f);
std::pair< std::list<float>::iterator, std::list<float>::iterator > res =
std::equal_range(ll3.begin(), ll3.end(), 40.0f);
std::cout << *res.first << " " << *res.second << std::endl;
std::cout << std::endl;
}
if (false) {
int tab1[5] = { 10, 20, 30, 40, 50 };
int tab2[5] = { 5, 15, 25, 35, 45 };
int tab3[10];
std::merge(tab1,tab1+5,tab2,tab2+5,tab3);
std::cout << "The merged list ";
std::for_each(tab3,tab3+10,Print<int>(" "));
std::cout << std::endl;
int tab4[10] = { 10, 20, 30, 40, 50, 5, 15, 25, 35, 45 };
std::inplace_merge(tab4,tab4+5,tab4+10);
std::cout << "The in-place merged list ";
std::for_each(tab4,tab4+10,Print<int>(" "));
std::cout << std::endl;
}
if (false) {
// The set algorithms allows set operations on sorted sequences.
int tab1[5] = { 10, 20, 30, 40, 50 };
int tab2[5] = { 10, 25, 30, 45, 50 };
int tab3[10];
// union
int* p = std::set_union(tab1,tab1+5,tab2,tab2+5,tab3);
std::cout << "Union ";
std::for_each(tab3,p,Print<int>(" "));
std::cout << std::endl;
// intersection
p = std::set_intersection(tab1,tab1+5,tab2,tab2+5,tab3);
std::cout << "Intersection ";
std::for_each(tab3,p,Print<int>(" "));
std::cout << std::endl;
// difference
p = std::set_difference(tab1,tab1+5,tab2,tab2+5,tab3);
std::cout << "Difference ";
std::for_each(tab3,p,Print<int>(" "));
std::cout << std::endl;
// symmetric difference
p = std::set_symmetric_difference(tab1,tab1+5,tab2,tab2+5,tab3);
std::cout << "Symmetric difference ";
std::for_each(tab3,p,Print<int>(" "));
std::cout << std::endl;
int tab4[3] = { 20, 30, 40 };
bool res = std::includes(tab1,tab1+5,tab4,tab4+3);
if (res)
std::cout << "Located the sequence in tab4 within tab1" << std::endl;
else
std::cout << "The sequence in tab4 is not located within tab1" << std::endl;
}
if (true) {
int tab[10] = { 2, 4, 6, 1, 3, 5, 8, 7, 9, 100 };
int* p = std::min_element(tab,tab+10);
std::cout << "Min value = " << *p << std::endl;
p = std::max_element(tab,tab+10);
std::cout << "Max value = " << *p << std::endl;
}
return 0;
}
Your post does not include a question. I will assume that you would have asked "What does this error message mean?"
The answer to that question is: std::ifstream is not copyable.
Your problem is that you're creating an instance of your File object and passing it to std::generate (around line 405). A File contains an instance of std::ifstream, and the functor is passed to std::generate by value, which means it receives a copy of the original object -- but since this object contains a std::ifstream, which can't be copied, that won't work.
As to how you find this: start by using an #if 0 to disable all your if (false) sections, and you'll find that it compiles and runs just fine.
From there, use bisection: enable half of them by moving the #if 0 down to (around) the middle of that huge block (and just before one of the if (false) lines). See if it still compiles. If it does, move the #if 0 down to about 3/4ths of the way down that section. If not, move it up to about 1/4th of the way through that chunk (and each time, assuring it's just before an if (false)). With a few iterations, you'll narrow it down to a single `if (false) chunk (that, in this case, is only 5 lines long). When it's that small, it's probably easiest to just look at the problem code.
The error is coming from line 407.
std::generate(v.begin(),v.end(),File<std::string>("c:/temp/items.txt"));
Which is stemming from the creation of your File object (defined earlier in the program). Now, if I understand what this line is doing correctly, you are populating the vector with each line of the fine (since the () operator constantly returns a line via the getline() function from the opened file). If you replace the following if block
if (false) {
std::vector<std::string> v(10);
std::generate(v.begin(),v.end(),File<std::string>("c:/temp/items.txt"));
std::for_each(v.begin(),v.end(),Print<std::string>("\n"));
std::cout << std::endl;
}
With this block
if (false) {
std::vector<std::string> v;
std::ifstream fi("c:/temp/items.txt");
std::string line;
while (!fi.eof ()) {
getline (fi, line);
v.push_back (line);
}
fi.close();
std::for_each(v.begin(),v.end(),Print<std::string>("\n"));
std::cout << std::endl;
}
Your program should run as expected, when you turn that if (false) to an if (true).
Also, you may want to include cstring, because you reference strcmp, which (at least for g++) needs the cstring header file.
Related
Is there a way to find duplicates effectively?
I'm trying to find duplicates even though they have been put in by user input. I've tried a few methods, for loop to do the checks but that doesnt work. Anyone got any idea how I might be able to do this effectively? #include <iostream> #include <algorithm> int main() { int size, * array; std::cout << "Indtast arrayet's stoerrelse." << std::endl; std::cin >> size; // optager input til størrelse af arrayet fra brugeren array = new int[size]; // dynamisk allokeret array while (size >= 100) { // while loop til at tjekke om arrayets størrelse er for stort std::cout << "Forkert input af array." << std::endl; break; } while (size <= 100) { // while loop til når arrayet er af rigtig størrelse float sum = 0; float gns = 0; std::cout << "Tast op til " << size << " vaerdier ind." << std::endl; for (int i = 0; i < size; i++) { // for loop til at optage input til hver element i arrayen std::cout << "Indtast vaerdi for array-nr: " << i << std::endl; std::cin >> array[i]; // optager input til hvert element sum += array[i]; // finder summen af elementerne i arrayet } std::cout << "Min-vaerdi er: " << *std::min_element(array, array + size) << std::endl; std::cout << "Max-vaerdi er: " << *std::max_element(array, array + size) << std::endl; std::cout << "Summen er: " << sum << std::endl; gns = sum / size; // udregner gennemsnittet std::cout << "Gennemsnittet er: " << gns << std::endl; return 0; } }
Here is a modern (C++20) approach using ranges. As suggested in the comments, you should sort your vector and then use adjacent_if. It is always recommended to use the algorithms from the standard library than to try to re-implement common stuff like this yourself using basic procedural tools like for and while loops. This approach would work with an array as well, but I suggest using an std::vector. #include <vector> #include <algorithm> #include <iostream> void print(std::vector<int> const& v){ // print the vector for (auto const& i: v){ std::cout << i << ", "; } std::cout<<"\n"; }; int main() { std::vector<int> v{1, 2, 1, 1, 3, 3, 3, 4, 5, 4}; std::cout << "Input vector = \t\t"; print(v); // sort the vector std::ranges::sort(v); std::cout << "Sorted vector = \t"; print(v); // find duplicates and print them auto it = std::ranges::adjacent_find(v); while (it != v.end()){ std::cout << "Duplicates start at v[" << std::distance(v.begin(), it) << "] = " << *it << "\n"; it = std::ranges::adjacent_find(it, v.end(), std::ranges::not_equal_to()); it = std::ranges::adjacent_find(it, v.end()); } for (; it != v.end(); ++it){ std::cout << *it << std::endl; } // remove duplicates auto ret = std::ranges::unique(v); v.erase(ret.begin(), ret.end()); std::cout << "No duplicates = \t"; print(v); return 0; } Output: Input vector = 1, 2, 1, 1, 3, 3, 3, 4, 5, 4, Sorted vector = 1, 1, 1, 2, 3, 3, 3, 4, 4, 5, Duplicates start at v[0] = 1 Duplicates start at v[4] = 3 Duplicates start at v[7] = 4 No duplicates = 1, 2, 3, 4, 5, Try it on compiler explorer: https://godbolt.org/z/YP3zb7PYf
Why is this ranged based for loop causing issues with subtraction?
I'm having an issue with a ranged based for loop causing my values to go negative, and I've resolved the issue with a regular for loop but want to understand why it messed up in the first place. You can see from the sample output below that the initial values exist correctly, but then when attempting to subtract from them, they get reset to a default initialized value of 0 I guess? Broken code: #include <iostream> #include <vector> #define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; } int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) { std::vector<int> multRank; multRank.resize(multipliers.size()); std::cout << "multRank: "; //ISSUE IS IN THE LOOP BELOW for (int n : multRank) { n = multipliers.size(); std::cout << " " << n; } std::cout << std::endl; for (auto i = 0; i < multipliers.size(); ++i) { for (auto j = 0; j < multipliers.size(); ++j) { int abs1 = std::abs(multipliers[i]); int abs2 = std::abs(multipliers[j]); if (abs1 > abs2) { multRank[i] = multRank[i] - 1; std::cout << multRank[i]; } } } std::cout << std::endl << "multRank after: "; for (int n : multRank) { std::cout << " " << n; } std::cout << std::endl << std::endl; return 0; } void test1() { std::vector<int> nums = { 1, 2, 3 }; std::vector<int> multipliers = { 3, 2, 1 }; int test = maximumScore(nums, multipliers); IS_TRUE(test == 14); } int main() { std::cout << "Maximum Score from Performing Multiplication Operations\n"; test1(); } Broken code output: Maximum Score from Performing Multiplication Operations multRank: 3 3 3 -1-2-1 multRank after: -2 -1 0 Repaired code: #include <iostream> #include <vector> #define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; } int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) { std::vector<int> multRank; multRank.resize(multipliers.size()); std::cout << "multRank: "; //ISSUE WAS IN THE LOOP BELOW for (auto i = 0; i < multipliers.size(); ++i) { multRank[i] = multipliers.size(); std::cout << " " << multRank[i]; } std::cout << std::endl; for (auto i = 0; i < multipliers.size(); ++i) { for (auto j = 0; j < multipliers.size(); ++j) { int abs1 = std::abs(multipliers[i]); int abs2 = std::abs(multipliers[j]); if (abs1 > abs2) { multRank[i]--; std::cout << multRank[i]; } } } std::cout << std::endl << "multRank after: "; for (int n : multRank) { std::cout << " " << n; } std::cout << std::endl << std::endl; return 0; } void test1() { std::vector<int> nums = { 1, 2, 3 }; std::vector<int> multipliers = { 3, 2, 1 }; int test = maximumScore(nums, multipliers); IS_TRUE(test == 14); } int main() { std::cout << "Calculate Rank\n"; test1(); } Repaired code output: Maximum Score from Performing Multiplication Operations multRank: 3 3 3 212 multRank after: 1 2 3
The first range based for loop is not using references: for (int n : multRank) { n = multipliers.size(); std::cout << " " << n; } In this loop, n is a copy of the data in multRank. If you want to be able to modify the data in multRank, you want n to be a reference: for (int& n : multRank) { n = multipliers.size(); std::cout << " " << n; }
How to traverse a map of the form pair<int,pair<int,int>> with a iterator
I defined map like map <int,pair<int,int>> hmap; If there is a pair(2,pair(3,4)) how to get 2 3 4 values, itr->first, itr->second not working
If there is a pair(2,pair(3,4)) how to get 2 3 4 values [from an iterator itr to map<int,pair<int, int>>] I suppose itr->first // 2 itr->second.first // 3 itr->second.second // 4
Here is a demonstrative program with using iterators and the range-based for statement. #include <iostream> #include <map> int main() { std::map<int, std::pair<int, int>> hmap{ { 1, { 2, 3 } }, { 2, { 3, 4 } } }; for (auto it = hmap.begin(); it != hmap.end(); ++it) { std::cout << "{ " << it->first << ", { " << it->second.first << ", " << it->second.second << " } }\n"; } std::cout << std::endl; for (const auto &p : hmap) { std::cout << "{ " << p.first << ", { " << p.second.first << ", " << p.second.second << " } }\n"; } std::cout << std::endl; } Its output is { 1, { 2, 3 } } { 2, { 3, 4 } } { 1, { 2, 3 } } { 2, { 3, 4 } }
Class destructor, runtime error: Unhandled exception - Stack overflow
The destructor for List appears to work, but having trouble with the destructor for Element and List_iter: Unhandled exception : 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x002E2F78). List: #ifndef GUARD_List_h #define GUARD_List_h #include "Element.h" #include "List_iter.h" template <typename T> class List { public: List() : begins(new Element<T>), ends(new Element<T>), Element_count(0) { begins->t_flag = 'b'; ends->t_flag = 'e'; // double link: begins & ends begins->next = ends; ends->prev = begins; } virtual ~List() { while (begins->next != ends) { begins->prev = begins->next; begins->next = begins->next->next; delete begins->prev; } delete begins; delete ends; } typedef List_iter<T> iterator; iterator begin(void) const { iterator it(begins); return it; } iterator end(void) const { iterator it(ends); return it; } void push_back(const T val) { Element<T>* elem = new Element<T>; // create: new-elem elem->data = val; // set data elem->prev = ends->prev; // link: new-elem to last-data-elem ends->prev->next = elem; // link: last-data-elem to new-Element elem->next = ends; // link: new-elem to List-end ends->prev = elem; // link: List-end to new-elem Element_count++; // update: when List grows } T at(const size_t pos) const { return get_Element(pos)->data; } void del(const size_t pos) const { Element<T>* elem = get_Element(pos); // get: Element for deletion elem->prev->next = elem->next; // rejoin: double link elem->next->prev = elem->prev; // rejoin: double link delete elem; Element_count--; // update: when List shrinks } void clear(void) { Element<T>* ep = begins->next; Element<T>* ep_next = ep->next; while (ep->t_flag != 'e'){ delete ep; ep = ep_next; ep_next = ep->next; } begins->next = ends; ends->prev = begins; //begins->data = 0r; //ends->elem_ID = 0; Element_count = 0; } size_t size(void) const { return Element_count; } bool empty(void) const { if (Element_count == 0){ return true; } else { return false; } } private: Element<T>* begins; // List begins Element<T>* ends; // List ends size_t Element_count; // List size Element<T>* get_Element(const size_t pos) const { if (empty()) { std::cerr << "No Element - Empty List"; throw; } if (pos < 0 || pos >= Element_count){ std::cerr << "No Element - Out of Range"; throw; } iterator it; // Determine the more efficent iteration direction(forward or reverse) ? if ((Element_count / 2) > pos) { it = begin(); for (size_t i = 0; i <= pos; i++){ it++; } } else { it = end(); for (size_t i = size() - pos; i > 0; i--){ it--; } } return it.elem; } }; #endif Element: #ifndef GUARD_Element_h #define GUARD_Element_h template <class T> class List; template <class T> class List_iter; template <class T> class Element { public: Element() : prev(nullptr), next(nullptr), data(), t_flag(' ') {} virtual ~Element() { delete prev; delete next; } friend List<T>; friend List_iter<T>; private: Element<T> *prev; Element<T> *next; T data; int elem_ID; char t_flag; }; #endif List_iter: #ifndef GUARD_List_iter_h #define GUARD_List_iter_h template <class T> class List; template <class T> class List_iter { public: List_iter(Element<T>* e = nullptr) : elem(e) {} virtual ~List_iter() { delete elem; } friend List<T>; T operator*(void){ if (elem->t_flag == 'e'){ elem = elem->prev; } else if (elem->t_flag == 'b'){ elem = elem->next; } return elem->data; } Element<T>* operator++(void) { if (elem->next->t_flag == 'e'){ return nullptr; } elem = elem->next; return elem; } Element<T>* operator--(void) { if (elem->prev->t_flag == 'b'){ return nullptr; } elem = elem->prev; return elem; } List_iter operator+(const int val) { for (int i = 0; i < val; i++){ this->elem = this->elem->next; } return *this; } List_iter operator-(const int val) { for (int i = 0; i < val; i++){ this->elem = this->elem->prev; } return *this; } bool operator!=(const List_iter& rhs) const { return rhs.elem != elem; } bool operator>(const List_iter& rhs) const { return (this->elem->elem_ID > rhs.elem->elem_ID); } bool operator<(const List_iter& rhs) const { return (this->elem->elem_ID < rhs.elem->elem_ID); } bool operator>=(const List_iter& rhs) const { return (this->elem->elem_ID >= rhs.elem->elem_ID); } bool operator<=(const List_iter& rhs) const { return (this->elem->elem_ID <= rhs.elem->elem_ID); } private: Element<T>* elem; }; #endif main: #include <iostream> #include "List.h" int main() { List<int> ls; List<int>::iterator begin = ls.begin(); List<int>::iterator end = ls.end(); List<int>::iterator iter = begin; std::cout << "Attempt to retrieve data from empty list: ls.at(3)" << std::endl; std::cout << "--------------------------------------------------" << std::endl; //std::cout << ls.at(3) << std::endl << std::endl; std::cout << "Test: growing list does not invalidate iter" << std::endl; std::cout << "-------------------------------------------" << std::endl; std::cout << "Empty list" << std::endl << std::endl; std::cout << "begin addr: " << &begin << " " << std::endl; std::cout << "end addr: " << &end << " " << std::endl; std::cout << std::endl << "Add data to list: 33 " << std::endl << std::endl; ls.push_back(33); std::cout << "begin addr: " << &begin << " " << std::endl; std::cout << "end addr: " << &end << " " << std::endl; std::cout << std::endl << "Add data to list: 856 " << std::endl << std::endl; ls.push_back(856); std::cout << "begin addr: " << &begin << " " << std::endl; std::cout << "end addr: " << &end << " " << std::endl; std::cout << "clear() " << std::endl << std::endl; ls.clear(); std::cout << std::endl << std::endl; std::cout << "Add data to list: 0 1 2 3 4 5 6 7 8 9" << std::endl; std::cout << "-------------------------------------------------" << std::endl; for (int i = 0; i != 10; i++){ ls.push_back(i); } std::cout << std::endl << std::endl; std::cout << "data# begin+4" << std::endl; std::cout << "-------------" << std::endl; std::cout << *(iter + 4) << std::endl; std::cout << std::endl << std::endl; std::cout << "data# begin->end" << std::endl; std::cout << "----------------" << std::endl; iter = begin; while (iter++){ std::cout << *iter << " "; } std::cout << std::endl << std::endl << std::endl; std::cout << "data# end->begin" << std::endl; std::cout << "----------------" << std::endl; iter = end; while (iter--){ std::cout << *iter << " "; } std::cout << std::endl << std::endl << std::endl; std::cout << "for/iter: begin->end" << std::endl; std::cout << "----------------" << std::endl; for (iter = begin; iter++;){ std::cout << *iter << " "; } std::cout << std::endl << std::endl << std::endl; std::cout << "iter arith: +4 +1 -1" << std::endl; std::cout << "--------------------" << std::endl; iter = ls.begin(); iter = iter + 4; std::cout << *iter << " "; std::cout << *(iter + 1) << " "; std::cout << *(iter - 1) << " "; std::cout << std::endl << std::endl << std::endl; std::cout << "data#: (0)(1)(2)(3)(4)(5)(6)(7)(8)(9)" << std::endl; std::cout << "-------------------------------------" << std::endl; for (int i = 0; i != 10; i++){ std::cout << ls.at(i) << " "; } //ls.clear(); List<std::string> ls_str; ls_str.push_back("Hello"); ls_str.push_back("World"); return 0; // breakpoint }
new Element called, therefore owned by List, so only List can delete Element. List_iter doesn't require a destructor because it only contains a pointer.
error: invalid operands of types 'const char[8]' and 'const char [17]' to binary 'operator<<'
The compiler isn't like my last std::cout line. I commented to specify where the error is occurring. I would love to hear some feedback on this. Thanks in advance. In addition, I would like, if you please, some general comments on my adherence to C++ coding practice and my contains repeats algorithm. I know that it's useless having that bool as the value in my std::map, but it's not possible to map a 1-dimensional map like std::map. Gotta add a value. #include <iostream> #include <map> #include <vector> void print_vector(std::vector<int>); bool contains_repeats_1(std::vector<int>); int main() { int arr1[] = {1, 5, 4, 3, -8, 3, 90, -300, 5, 69, 10}; std::vector<int> vec1(arr1, arr1 + sizeof(arr1)/sizeof(int)); std::cout << "vec1 =" << std::endl; print_vector(vec1); int arr2[] = {1, 6, 7, 89, 69, 23, 19, 100, 8, 2, 50, 3, 11, 90}; std::vector<int> vec2(arr2, arr2 + sizeof(arr2)/sizeof(int)); std::cout << "vec2 =" << std::endl; print_vector(vec2); std::cout << "vec1 " << contains_repeats_1(vec1) ? "does" : "doesn't" << " contain repeats" << std::endl; // ^^^^^^ ERROR return 0; } void print_vector(std::vector<int> V) { std::vector<int>::iterator it = V.begin(); std::cout << "{" << *it; while (++it != V.end()) std::cout << ", " << *it; std::cout << "}" << std::endl; } bool contains_repeats_1(std::vector<int> V) { std::map<int,bool> M; for (std::vector<int>::iterator it = V.begin(); it != V.end(); it++) { if (M.count(*it) == 0) { M.insert(std::pair<int,bool>(*it, true)); } else { return true; } return false; } }
The conditional operator ?: has a fairly low precedence (lower than <<), so you need to add parenthesis. std::cout << "vec1 " << (contains_repeats_1(vec1) ? "does" : "doesn't") << " contain repeats" << std::endl;
<< has higher precedence than ?: std::cout << "vec1 " << (contains_repeats_1(vec1) ? "does" : "doesn't") << " contain repeats" << std::endl;