error C2794: 'iterator_category': is not a member of any direct or indirect base class of 'std::iterator_traits<_Iter>'

My code:
1
2
3
4
5
6
7
8
9
10
11
12
template<typename Iter1, typename Iter2>
Iter2 mycode::copy(Iter1 f1, Iter1 e1, Iter2 f2)
{
	if (f1 == e1)
	{
		std::cout << "List is empty. Nothing to copy.\n";
		std::cout << "Giving back original container iterator.\n";
		return f2;
	}
	std::copy(f1, e1, f2);
	return f2;
}
Show the setup and code that actually calls your template function. From the looks of it, it seems you aren't passing an actual iterator into your code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <list>
#include "../../cust_std_lib_facilities.h"

namespace mycode
{
	template<typename Iter1, typename Iter2>
	Iter2 copy(Iter1 f1, Iter1 e1, Iter2 f2);
}

int main()
{
	int arr[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	std::vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	std::list<int> lst{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	constexpr std::size_t size = 10;
	int arr2[size] = { 0 };
	std::copy(arr, arr + size, arr2);
	std::vector<int> vec2 = vec;
	std::list<int> lst2 = lst;
	
	std::cout << "original array:\n";
	for (std::size_t i = 0; i < size; ++i)
	{
		std::cout << arr[i] << '\n';
	}
	std::cout << "array copy:\n";
	for (std::size_t i = 0; i < size; ++i)
	{
		std::cout << arr2[i] << '\n';
	}
	std::cout << '\n';
	for (std::size_t i = 0; i < size; ++i)
	{
		arr2[i] = i + 2;
		arr[i] = i + 2;
	}
	std::cout << "both arrays with each element value increased by 2:\n";
	for (std::size_t i = 0; i < size; ++i)
	{
		std::cout << arr[i] << '\n';
	}
	std::cout << '\n';
	for (std::size_t i = 0; i < size; ++i)
	{
		std::cout << arr2[i] << '\n';
	}

	std::cout << "original vector:\n";
	for (const int &x : vec)
	{
		std::cout << x << '\n';
	}
	std::cout << '\n';
	std::cout << "copy vector:\n";
	for (const int &x : vec2)
	{
		std::cout << x << '\n';
	}

	for (std::size_t i = 0; i < vec.size(); ++i)
	{
		vec2[i] = i + 3;
		vec[i] = i + 3;
	}
	std::cout << "both vectors with each element value increased by 3:\n";
	for (const int x : vec)
	{
		std::cout << x << '\n';
	}
	std::cout << '\n';
	for (const int x : vec2)
	{
		std::cout << x << '\n';
	}

	std::cout << "original linked list:\n";
	for (const int x : lst)
	{
		std::cout << x << '\n';
	}
	std::cout << "copy linked list:\n";
	for (const int x : lst2)
	{
		std::cout << x << '\n';
	}

	for (auto iter = lst.begin(); iter != lst.end(); ++iter)
	{
		*iter += 5;
	}

 	for (auto iter = lst2.begin(); iter != lst2.end(); ++iter)
	{
		*iter += 5;
	}

	std::cout << "both linked lists with each element value increased by 5:\n";
	for (const int x : lst)
	{
		std::cout << x << '\n';
	}
	std::cout << '\n';
	for (const int x : lst2)
	{
		std::cout << x << '\n';
	}

	std::cout << "array copied into vector:\n";
	mycode::copy(arr, arr + size, vec);
	for (const int x : vec)
	{
		std::cout << x << '\n';
	}

	std::cout << "list copied into array:\n";
	mycode::copy(lst.begin(), lst.end(), arr);
	for (std::size_t i = 0; i < size; ++i)
	{
		std::cout << arr[i] << '\n';
	}
}

template<typename Iter1, typename Iter2>
Iter2 mycode::copy(Iter1 f1, Iter1 e1, Iter2 f2)
{
	if (f1 == e1)
	{
		error("List is empty. Nothing to copy");
	}
	for (Iter1 i = f1; i != e1; ++i)
	{
		for (Iter2 j = f2; j != (f2 + (e1 - f1)); ++j)
		{
			*j = *i;
		}
	}
	return f2;
}


This is for a Drill in the book PPP2, which is like this:
1. Define an array of int s with the ten elements { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.
2. Define a vector<int> with those ten elements.
3. Define a list<int> with those ten elements.
4. Define a second array, vector, and list, each initialized as a copy of the first
array, vector, and list, respectively.
5. Increase the value of each element in the array by 2; increase the value of
each element in the vector by 3; increase the value of each element in the
list by 5.
6. Write a simple copy() operation,
template<typename Iter1, typename Iter2>
// requires Input_iterator<Iter1>() && Output_iterator<Iter2>()
Iter2 copy(Iter1 f1, Iter1 e1, Iter2 f2);
that copies [f1,e1) to [f2,f2+(e1–f1)) and returns f2+(e1–f1) just like the
standard library copy function. Note that if f1==e1 the sequence is empty,
so that there is nothing to copy.
7. Use your copy() to copy the array into the vector and to copy the list into
the array.


There's also a number 8, but I haven't gotten to that part yet.
Last edited on
As Ganado said,

1
2
3
std::vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// ...
mycode::copy(arr, arr + size, vec);

here, vec is not an iterator
ffs cplusplus.com deleted what I wrote.

UUUUUGH. Okay... retyping with reduced quality:

1st compiler error
1
2
3
4
5
prog.cpp: In instantiation of ‘Iter2 mycode::copy(Iter1, Iter1, Iter2) [with Iter1 = int*; Iter2 = std::vector<int>]’:
prog.cpp:112:35:   required from here
prog.cpp:135:31: error: no match foroperator+’ (operand types are ‘std::vector<int>’ and ‘long int’)
   for (Iter2 j = f2; j != (f2 + (e1 - f1)); ++j)
                           ~~~~^~~~~~~~~~~~


Line 113: vec is an std::vector<int>, not an iterator. It might seem weird that you can't pass a vector like you can a raw C array, but you gotta use vec.begin() to get the iterator to vec.
mycode::copy(arr, arr + size, vec.begin());

2nd compiler error
1
2
3
4
5
prog.cpp: In instantiation of ‘Iter2 mycode::copy(Iter1, Iter1, Iter2) [with Iter1 = std::_List_iterator<int>; Iter2 = int*]’:
prog.cpp:119:42:   required from here
prog.cpp:135:37: error: no match foroperator-’ (operand types are ‘std::_List_iterator<int>’ and ‘std::_List_iterator<int>’)
   for (Iter2 j = f2; j != (f2 + (e1 - f1)); ++j)
                                 ~~~~^~~~~


Line 120: You pass in list iterators into your template function.
Line 136: You use the - operator between e1 and f1.
A list iterator is bidirectional, and cannot use + or - operators. You must advance the vector either by using std::advance or by just using the ++ or -- operators yourself.

Copying a 1-dimensional array should not require 2 for-loops. Instead of doing the 2x for loops and ending on j != (f2 + (e1 - f1)), you should advance the f1 iterator and f2 iterator (using the ++ operator), and end the loop on the condition of f1 != e1. This will also correctly iterate the f2 iterator so that it can be returned as is (returning the equivalent of f2 + (e1 - f1) ).
Last edited on
For the first error: Yeah, I messed up. I do know that about std::vector vs. a built-in array, though.

For the second error: Then should I just do for (Iter1 i = f1; i != e1; ++i)?

Do note that f2 is an Iter2, not an Iter1. If I tried to do
for (Iter1 i = f1, j = f2 ...), won't that give me an error?
constexpr std::size_t size = 10;
this is not required:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    
int arr[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int arr_copy [std::end(arr)-std::begin(arr)] = {0};
std::copy(std::begin(arr), std::end(arr), std::begin(arr_copy));
for (const auto & elem : arr_copy)std::cout << elem << " ";
}

http://coliru.stacked-crooked.com/a/ae337f04bc635583
DragonOsman, that isn't what I would personally do, although what I'm thinking certainly isn't the only way to solve it. You want to copy [f1, e1), so I would use a while loop, and end the while loop on while (f1 != e1). Inside each iteration of the while loop, you should be incrementing both f1 and f2, and then return the incremented f2 at the end of the function.
Last edited on
For me the for-loop is easier to do. But yeah, a while-loop would also work just fine. This is what I have now, though:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<typename Iter1, typename Iter2>
Iter2 mycode::copy(Iter1 f1, Iter1 e1, Iter2 f2)
{
	if (f1 == e1)
	{
		error("List is empty. Nothing to copy");
	}
	Iter2 j = f2;
	for (Iter1 i = f1; i != e1; ++i, ++j)
	{
		*j = *i;
	}
	return f2;
}


I have another now, though. When trying to do part 8 of the Drill.

On this code:
1
2
3
4
5
6
7
8
9
10
if (std::find(vec.begin(), vec.end(), 3) != vec.end())
{
	auto pos = std::find(vec.begin(), vec.end(), 3);
	std::cout << "\nThe value 3 is at position " << pos << " in the original vector\n";
}
if (std::find(vec2.begin(), vec2.end(), 3) != vec2.end())
{
	auto pos = std::find(vec2.begin(), vec2.end(), 3);
	std::cout << "\nThe value 3 is at position " << pos << " in the copy vector\n";
}


I have the error message (on the lines where I'm trying to print pos):
error C2679: binary '<<': no operator found which takes a right-hand operand of type 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>' (or there is no acceptable conversion)


Anyone have any idea how to fix this?

This is part 8, by the way:
Use the standard library find() to see if the vector contains the value 3
and print out its position if it does; use find() to see if the list contains the
value 27 and print out its position if it does. The “position” of the first
element is 0, the position of the second element is 1, etc. Note that if find()
returns the end of the sequence, the value wasn’t found.


I'm on the part where it says to find the value 3 in the vector.
Last edited on
Your compiler error is saying that it can't find a way to use the '<<' operator on a Vector_iterator. That means it doesn't know how to print an iterator using std::cout << my_iter.

The return type of std::find is an iterator to the found element (or an iterator to the end of the vector if the element was not found).
To get the index of that element by using the iterator, you should use std::distance.

std::cout << "index: " << std::distance(vec.begin(), pos) << std::endl;
Last edited on
Yeah, thanks. That did work for me.
Topic archived. No new replies allowed.