Template funtion returning an iterator - c++

i would like to make a reusable function that returns an iterator to make it easy to find the middle point of a container and need some help
fixed;
template <typename T> std::vector<int>::const_iterator middlepoint(std::vector<T> const& arr){
auto temp = arr.begin() + arr.size() / 2;
return temp;
}
the caller:
auto middle_point = middlepoint(arr.begin(), arr.end());
fixed:
template <typename T> int middlepoint(std::vector<T> const& arr){
std::cout << "size: " << arr.size() << endl;
auto middle_point = arr.begin() + (arr.size()/ 2);
int middle_element = middle_point - arr.begin();
return middle_element;
}
caller:
int middle_element = middlepoint(arr);
error:
ambiguous
ambiguous, means you declared 2 functions with the same name, but different parameters.

It looks like you're taking the beginning and end iterators and dividing them by 2 to get the middle position. Iterators don't have a valid expression for division, so what you're doing won't work.
The best way I can think to implement this would be to use the size of the container divided by 2 as an offset from the beginning or the end (whichever works best for you). This way you wouldn't need to pass both iterators to the function.
auto mid = it.begin() + (arr.size() / 2); original
return mid;
If you can't get the size of the container using the .size() method (which you should be able to because you have access to the iterators), you can create a helper function that cycles through and counts. That shouldn't be needed for your case though because you're using a vector.

Related

Fast STL way to find input that produces maximum output of function? (contiguous integer inputs)

To improve the readability, I'm trying to get out of the habit of reinventing the wheel.
Problem:
Consider a black-box function, Foo, which has an integer as input and output. We want to find the input that maximises the output. Consider that all the possible inputs belong to a single, contiguous range of integers; and that the range is small enough that we can try each one.
Speed is important, so we don't use containers. Even if the user has already created a container for all the possible inputs, it's still about 100x faster to calculate the next input (++input) than to get it from memory (cache misses).
Example:
Range: [5, 8)
Foo(5); // 19
Foo(6); // 72
Foo(7); // 31
We want to make a function that should return 6:
InputOfMaxOutputOnRange(5, 8, Foo); // 6
Custom solution:
template <typename T, typename Func>
T InputOfMaxOutputOnRange (T begin_range, T end_range, Func && Scorer)
{
// initialise:
auto max_o = Scorer(begin_range);
T i_of_max_o = begin_range;
// now consider the rest of the range:
++begin_range;
for (T i = begin_range; i < end_range; ++i)
{
auto output = Scorer(i);
if (max_o < output)
{
max_o = output;
i_of_max_o = i;
}
}
return i_of_max_o;
}
Question:
I use functions like this so often that I think there should be an STL way to do it. Is there?
C++20 ranges can do this:
template<typename T, typename F>
T argmax_iota(T begin, T end, F &&score) { // can't really think of a good name for this; maybe it doesn't even deserve its own function
return std::ranges::max(std::views::iota(begin, end), std::less{}, std::ref(score));
// over the values in the range [begin, end) produced by counting (iota)...
// find the one that produces the greatest value (max)...
// when passed to the projection function score...
// with those values under the ordering induced by std::less
}
Godbolt
iota does not store the whole range anywhere. Iterators into the range hold a single T value that is incremented when the iterator is incremented.
In general, the algorithms in the STL work on sequences of values, that are traversed by iterators. They tend to return iterators as well. That's the pattern that it uses.
If you're doing a lot of things like this, where your input "sequence" is a sequential list of numbers, then you're going to want an iterator that "iterates" over a sequence (w/o any storage behind it).
A little bit of searching turned up Boost.CountingIterator, which looks like it could do what you want. I'm confident that there are others like this as well.
Warning - completely untested code
auto iter = std::max_element(boost::counting_iterator<int>(5),
boost::counting_iterator<int>(8),
// a comparator that compares two elements
);
return *iter; // should be '6'
As others have observed, std::max_element is defined to get the largest element in a a range.
In your case, the "iterator" is an integer, and the result of dereferencing that iterator is...some result that isn't related to the input in an obvious (but apparently you have some way to getting it efficiently nonetheless).
This being the case, I'd probably define a specialized iterator class, and then use it with std::max_element:
#include <iostream>
#include <iterator>
#include <algorithm>
// your association function goes here. I've just done something
// where the relationship from input to output isn't necessarily
// immediately obvious
int association_function(int input) {
int a = input * 65537 + 17;
int b = a * a * a;
return b % 127;
}
class yourIterator {
int value;
public:
// create an iterator from an int value
explicit yourIterator(int value) : value(value) {}
// "Deference" the iterator (get the associated value)
int operator*() const { return association_function(value); }
// advance to the next value:
yourIterator operator++(int) {
yourIterator temp(value);
++value;
return temp;
}
yourIterator &operator++() {
++value;
return *this;
}
// compare to another iterator
bool operator==(yourIterator const& other) const { return value == other.value; }
bool operator!=(yourIterator const& other) const { return value != other.value; }
// get the index of the current iterator:
explicit operator int() const { return value; }
};
int main() {
// For demo, print out all the values in a particular range:
std::cout << "values in range: ";
std::copy(yourIterator(5), yourIterator(10), std::ostream_iterator<int>(std::cout, "\t"));
// Find the iterator that gives the largest value:
yourIterator max = std::max_element(yourIterator(5), yourIterator(10));
// print out the value and the index that gave it:
std::cout << "\nLargest element: " << *max << "\n";
std::cout << "index of largest element: " << static_cast<int>(max);
}
When I run this, I get output like this:
values in range: 64 90 105 60 33
Largest element: 105
index of largest element: 7
So, it seems to work correctly.
If you need to use this with a variety of different association functions, you'd probably want to pass that as a template parameter, to keep the iteration part decoupled from the association function.
// pass association as a template parameter
template <class Map>
class mappingIterator {
int value;
// create an instance of that type:
Map map;
public:
// use the instance to map from iterator to value:
int operator*() const { return map(value); }
Then you'd have to re-cast your association function into a form suitable for use as a template parameter, such as:
struct association_function {
int operator()(int input) const {
int a = input * 65537 + 17;
int b = a * a * a;
return b % 127;
}
};
Then in main you'd probably want to define a type for the iterator combined with an association function:
using It = mappingIterator<association_function>;
It max = std::max_element(It(5), It(10));
You can use std::max_element defined in <algorithm>.
This will return the iterator to the maximum element in a specified range. You can get the index using std::distance.
Example copied from cppreference.
std::vector<int> v{ 3, 1, -14, 1, 5, 9 };
std::vector<int>::iterator result;
result = std::max_element(v.begin(), v.end());
std::cout << "max element at: " << std::distance(v.begin(), result) << '\n';

How can I create a new array from the array returned by a function?

I have a method to shuffle arrays, but it's not working and I don't know how to fix it now. How can I create a new array in main from the array returned by shuffleArray as I can't assign the shuffled array to a new array and it's giving me the same index for the elements?
using namespace std;
template <class T> T min (T array, T size){
int min=array[0];
for(int i=1;i<size;i++){
if(array[i]<min){min=array[i];}
}
return min;
}
template <class T> T indexOf (T array[], const int size, T value){
for(int i=0;i<size;i++){
if(array[i]==value){return value;}
}
return -1;
}
template <class T> T shuffleArray (T array[], T size){
T* Array2 = new T[size];
for(int i=0;i<size;i++){
Array2[i]=array[i];
}
random_shuffle(&Array2[0],&Array2[size]);
return *Array2;
}
int main(){
int a[]= {1,2,3,4,5};
int index = indexOf(a, 5, 3);
cout << endl << "The index is:" << shuffleArray(a, 5)<<endl;
cout << endl << "The index is:" << index<<endl;
return 0;
}
Short Answer: Use std container as std::array, they have appropriate copy constructors and save you some headache. By the way std::array is also not slower as a raw array (it is basically the raw array, but wrapped in a class and given some nice member functions to work with it).
Detailed Answer: I am not entirely sure, what you like to print to std::cout. But most likely it should be the position of 3 before and after shuffling. Then the code should look like this (to compile with std=c++11 for use of constexpr and auto):
#include <iostream>
#include <algorithm> // std::min, std::find and std::random_shuffle
#include <array> // use std::array instead of raw pointers
// using namespace std; Bad idea, as tadman points out in comment
// use std::min instead of
// template <class T> T min (T array, T size)
// use std::find instead of
// template <class T> T indexOf (T array[], const int size, T value){
// T is not the value_type of the array, but the array iteself. Works also for all other std containers with random access iterators
template<class T> T shuffleArray(T array) // array is copied here
{
// shuffle
std::random_shuffle(array.begin(), array.end());
// return copy of array
return array;
}
int main()
{
constexpr int numberToFind = 3; // constexpr is not necessary, but the variable seems not intented to change in this code
// use standard container instead of raw array
std::array<int,5> a = {1,2,3,4,5};
// iterator to numberToFind in a
auto it = std::find(a.begin(), a.end(), numberToFind); // auto deduces the type, so you do not have to write std::array<int,t>::iterator and by the way the code is more flexible for changes
// shuffle a and store result in aShuffled
auto aShuffled = shuffleArray(a);
// iterator to numberToFind in aShuffled
auto itShuffled = std::find(aShuffled.begin(), aShuffled.end(), numberToFind);
// pointer arithmetics give the index
std::cout << "The index before shuffling is:" << it - a.begin() << std::endl;
std::cout << "The index after shuffling is:" << itShuffled - aShuffled.begin() << std::endl;
return 0;
}
As some comments already tell you, a few tips for the future:
Use std containers instead of raw pointers of raw arrays
Use well tested algorithms from the standard library instead of writing your own, unless you have very specific needs
auto makes live very easy in C++11 to handle also the iterator types. By the way you have to change almost nothing to use std::vector instead of std::array. The first declaration is enough.
Always when you use a new there has to be a delete. Otherwise you create a memory leak. Again this can be generally avoided by using the standard container.
Use descriptive names instead of literals. This makes your code more clear and readable.

Is it ok to reference a part of a std::vector subtracted from end()

Here is my code which attempts to search for a string of chars "gold" in the last four elements of a vector. It does successfully find the string but is this safe to do? It works on MS VS2008.
#include <vector>
#include <iostream>
int main() {
char random[] = {'a','b','c','d','e','f','g'};
char tofind2[] = {'g','o','l','d'};
std::vector<char> buf;
buf.insert(buf.end(), random, random+sizeof(random));
buf.insert(buf.end(), tofind2, tofind2+sizeof(tofind2));
if(buf.size() >= sizeof(tofind2) && std::equal(buf.end()-sizeof(tofind2), buf.end(), tofind2)) {
std::cout << "found value in last " << sizeof(tofind2) << " elements of array\n";
}
}
This is safe so long as your vector has at least 4 elements in it: iterators in general can be moved through the bounds of their range, and random access iterators can be moved via addition/subtraction of an integer type. std::vector's iterators are random access iterators.
If it has less than 4 elements, this is not safe, and leads to undefined behavior (even before you dereference the iterator!)
If you want to be careful, you should check for that case.
template<typename Container>
auto nth_last_iterator( Container&& c, int n )
-> declval( std::begin(c) )
{
if (n > std::end(c) - std::begin(c))
n = std::end(c) - std::begin(c);
return std::end(c)-n;
}
which is C++11 and works on any random access container. Then you get:
if(std::equal(nth_last_iterator(buf,sizeof(tofind2)), buf.end(), tofind2)) {
std::cout << "found value in last " << sizeof(tofind2) << " elements of array\n";
}
As noted by #DavidHammen, sizeof(tofind2) only works if sizeof(tofind2[0]) == 1. There are some relatively easy to write templates that find the size of an array and don't have that weakness, such as:
template<typename T, std::size_t N>
std::size_t lengthof( T(&)[N] ) {
return N;
}
which is valid C++03, and in C++11 you can make it constexpr. (and you can extend it to std::array< T, N > const& as well)
This is correct, you can safely do that since iterator arithmetic is allowed (http://www.cplusplus.com/reference/iterator/RandomAccessIterator/).

Apply std::begin() on an dynamically allocated array in a unique_ptr?

I have an unique pointer on a dynamically allocated array like this:
const int quantity = 6;
unique_ptr<int[]> numbers(new int[quantity]);
This should be correct so far (I think, the [] in the template parameter is important, right?).
By the way: Is it possible to initialize the elements like in int some_array[quantity] = {}; here?
Now I was trying to iterate over the array like this:
for (auto it = begin(numbers); it != end(numbers); ++it)
cout << *it << endl;
But I cannot figure out, how the syntax is right. Is there a way?
Alternatively I can use the index like:
for (int i = 0; i < quantity; ++i)
cout << numbers[i] << endl;
Is one of these to be preferred?
(Not directly related to the title: As a next step I would like to reduce that to a range-based for loop but I just have VS2010 right now and cannot try that. But would there be something I have to take care of?)
Thank you! Gerrit
Compiler is supposed to apply this prototype for std::begin:
template< class T, size_t N >
T* begin( T (&array)[N] );
It means the parameter type is int(&)[N], neither std::unique_ptr nor int *. If this is possible, how could std::end to calculate the last one?
But why not use raw pointer directly or a STL container?
const int quantity = 6;
std::unique_ptr<int[]> numbers{new int[quantity]};
// assignment
std::copy_n(numbers.get(), quantity,
std::ostream_iterator<int>(std::cout, "\n"));
const int quantity = 6;
std::vector<int> numbers(quantity, 0);
// assignment
std::copy(cbegin(numbers), cend(numbers),
std::ostream_iterator<int>(std::cout, "\n"));
Dynamically allocated arrays in C++ (ie: the result of new []) do not have sizing information. Therefore, you can't get the size of the array.
You could implement std::begin like this:
namespace std
{
template<typename T> T* begin(const std::unique_ptr<T[]> ptr) {return ptr.get();}
}
But there's no way to implement end.
Have you considered using std::vector? With move support, it shouldn't be any more expensive than a unique_ptr to an array.

C++ trying to swap values in a vector

This is my swap function:
template <typename t>
void swap (t& x, t& y)
{
t temp = x;
x = y;
y = temp;
return;
}
And this is my function (on a side note v stores strings) call to swap values but whenever I try to call using values in a vector I get an error. I'm not sure what I'm doing wrong.
swap(v[position], v[nextposition]); //creates errors
I think what you are looking for is iter_swap which you can find also in <algorithm>.
all you need to do is just pass two iterators each pointing at one of the elements you want to exchange.
since you have the position of the two elements, you can do something like this:
// assuming your vector is called v
iter_swap(v.begin() + position, v.begin() + next_position);
// position, next_position are the indices of the elements you want to swap
Both proposed possibilities (std::swap and std::iter_swap) work, they just have a slightly different syntax.
Let's swap a vector's first and second element, v[0] and v[1].
We can swap based on the objects contents:
std::swap(v[0],v[1]);
Or swap based on the underlying iterator:
std::iter_swap(v.begin(),v.begin()+1);
Try it:
int main() {
int arr[] = {1,2,3,4,5,6,7,8,9};
std::vector<int> * v = new std::vector<int>(arr, arr + sizeof(arr) / sizeof(arr[0]));
// put one of the above swap lines here
// ..
for (std::vector<int>::iterator i=v->begin(); i!=v->end(); i++)
std::cout << *i << " ";
std::cout << std::endl;
}
Both times you get the first two elements swapped:
2 1 3 4 5 6 7 8 9
There is a std::swap in <algorithm>
after passing the vector by reference
swap(vector[position],vector[otherPosition]);
will produce the expected result.
Using std::swap by including the <algorithm> library to swap values by references / smart pointers,
e.g. std::swap(v[0], v[1])
Note: v[i] is a reference
Using std::iter_swap from the same library,
e.g. std::iter_swap(v.begin(), v.begin() + v.size() - 1)
Using lvalue references and rvalue tuple by including the <tuple> library
e.g. std::tie(v[0], v[1]) = std::make_tuple(v[1], v[0])
Note: constexpr since C++14