How to do the calculation with std::transform - c++

I have a void function that takes as arguments iterators to the start and the end of a set of points (Setiterator set_begin, Setiterator set_end),a query point to perform some calculations and a iterator to the beginnig of a set of points ( where I am going to add the results)
void computedist(Setiterator set_begin, Setiterator set_end,
Vector const& query_point, DistanceIterator dist_begin )
{
std::transform(set_begin, set_end, dist_begin, calculation);
}
I have read that with std::transform I can do that calculations over the whole set of points, but I don't know how should I define the calculation to be done, as I am new to C++.
In this case, I want to compute the distance of the points to the query point:
I guess that my calculation should look like this
double calc_dist(double query_point, double point_of_the_set){
double dist;
dist = fabs(query_point - point_of_the_set);
return dist;
But I don't know how should I give the arguments to the function, since I am new to working with iterators.
Thank's!

The flavor of std::transform you are calling expects a UnaryOp function to call, to which it passes '*iterator' by const reference and expects a return value of the iterator::value_type which it writes to *dest.
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
using valtype = int;
std::vector<valtype> v1 { 1, 2, 3, 4, 5 };
std::vector<valtype> v2(v1.size());
std::transform(v1.begin(), v1.end(), v2.begin(),
[] (const valtype& in) { return in * 2; });
for (auto& val : v2)
std::cout << val << '\n';
}
Live demo: http://ideone.com/CUUlvA

Related

Accumulate Every Other Element in a Vector C++

I want to be able to accumulate every other pair of elements in a vector using accumulate. I tried the following without much success, returning an error for a non-empty, non-zero vector
return std::accumulate(vec.begin(), vec.end(), 0,
[&](int runningSum, int first, int second)
{return runningSum = runningSum + min(first, second);});
which I now realise probably wouldn't be getting the minimum between pairs. For instance, if I have
vector<int> vec = {1,4,2,3}
I want to return 0 + min(1, 4) + min(2, 3).
On another note, is there any website with many examples of these STL built-ins? I find the examples online far and few. I really want to see the power of accumulate, and get comfortable with it.
std::accumulate() does not allow you to use a predicate with 3 parameters, only 2 parameters - the current running sum, and the current element to be added to that sum. The predicate is called for each individual element and is expected to return the updated sum.
If you want to sum the values in pairs, you can try something like this instead:
vector<int> vec = {1,4,2,3};
...
int *first = nullptr;
return std::accumulate(vec.begin(), vec.end(), 0,
[&](int runningSum, int &value) {
if (first) {
runningSum += std::min(*first, value);
first = nullptr;
} else {
first = &value;
}
return runningSum;
}
);
A better solution would be to simply change your vector to hold a pair of ints (like std::pair<int, int>) as its element type (or at least copy your vector ints to a second vector of pairs), and then you can accumulate the pairs as-is:
vector<pair<int,int>> vec = {{1,4},{2,3}};
...
return std::accumulate(vec.begin(), vec.end(), 0,
[](int runningSum, const pair<int, int> &p) {
return runningSum + std::min(p.first, p.second);
}
);
I think it would be difficult to just use accumulate straight away to sum by min of pairs. You would need to maybe split your existing vector first, then transform them into a vector of the mins, then you could use the accumulate function.
So with that in mind, I would maybe do it like this:
std::vector<int> v{ 1,4,2,3};
std::vector<int> v2;
std::vector<int> v3;
std::vector<int> v4;
std::partition_copy(begin(v),
end(v),
back_inserter(v2),
back_inserter(v3),
[toggle = false](int) mutable { return toggle = !toggle; });
std::transform(begin(v2), end(v2), begin(v3), std::back_inserter(v4), [](auto a, auto b)
{
return std::min(a,b);
});
auto sum_of_min_in_pairs = std::accumulate(begin(v4), end(v4), 0);
Note that the code above will have issues if your vector does not have even amount of elements. Otherwise, transform it into a pair, with some default to match the remainder, depending on what you want to achieve.
With the STL website, cppreference.com is your friend. There are also a few books around I would highly recommend.
Effective STL by Scott Meyers
The C++ standard library by Nicolai Josuttis
I would solve this using std::adjacent_difference and std::accumulate:
#include <algorithm> // std::min
#include <iostream>
#include <numeric> // std::adjacent_difference, std::accumulate
#include <vector>
int main()
{
std::vector v{1, 4, 3, 2, 3, 8, 5, 1};
std::adjacent_difference(
v.cbegin(), v.cend(), v.begin(),
[](auto lhs, auto rhs) { return std::min(lhs, rhs); });
auto is_second_elem{true};
std::cout << std::accumulate(cbegin(v), cend(v), 0,
[&is_second_elem](auto acc, auto min) {
is_second_elem = not is_second_elem;
return is_second_elem ? (acc + min) : acc;
})
<< '\n'; // 7
}

How do you perform transformation to each element and append the result in c++?

I have a set of integers {1,2}. I want to produce "Transform#1, Transform#2" where each element is tranformed and then result is accumulated with a delimiter.
What would be the easiest way to accomplish this? Do we have "folds", "maps" in c++?
We dont use boost.
You can use std::transform and std::accumulate
int main()
{
std::vector<int> v1 {1,2,3};
std::vector<std::string> v2;
std::transform(begin(v1), end(v1), std::back_inserter(v2), [](auto const& i) {
return std::string("Transform#") + std::to_string(i);
});
std::string s = std::accumulate(std::next(begin(v2)), end(v2), v2.at(0), [](auto const& a, auto const& b) {
return a + ", " + b;
});
std::cout << s;
}
prints Transform#1, Transform#2, Transform#3
You may want to use Range Adaptors. Boost already has them and they are coming to the standard with C++20.
Take a look at the boost::adaptors::transformed example here.
Also, check out the reference to get a better picture of what operations are supported by adaptors.
In the end, you can achieve much cleaner code and the performance difference is negligible (unlike in some other languages, where using this style of programming incurs heavy performance costs).
If you can stand a trailing separator, the following function can transform any iterable range of data { X, ..., Z } to the string "<tag>X<sep>...<sep><tag>Z<sep>".
Code
template <class InputIt>
std::string f(InputIt begin, InputIt end, std::string_view separator = ", ", std::string_view tag = "Transform#")
{
std::stringstream output;
std::transform(begin, end,
std::ostream_iterator<std::string>(output, separator.data()),
[tag](auto const& element){ return std::string{tag} + std::to_string(element); }
);
return output.str();
}
It works by transforming each element from the range into a stream iterator.
Usage
int main()
{
std::set<int> const data{1, 2, 3}; // works with vector, string, list, C-arrays, etc.
std::cout << f(begin(data), end(data)) << '\n';
// prints Transform#1, Transform#2, Transform#3,
}
Live demo
You can perform a fold using simply std::accumulate
#include <set>
#include <string>
#include <iostream>
#include <numeric>
int main()
{
auto transformation = [](int number) { return "Transform#" + std::to_string(number); };
auto transform_and_fold = [&transformation](std::string init, int number) { return std::move(init) + ", " + transformation(number); };
std::set<int> numbers{1, 2};
std::cout << std::accumulate(std::next(numbers.begin()), numbers.end(), transformation(*numbers.begin()), transform_and_fold);
}
Outputs
Transform#1, Transform#2
Assuming that I correctly understand the problem, the following straightforward implementation also looks very simple and easy.
This function works in C++11 and over:
DEMO with 5 test cases
std::string concatenate(
const std::vector<int>& indecies,
const std::string& delimiter = ", ",
const std::string& tag = "Transform#")
{
if(indecies.empty()){
return "";
}
std::string s(tag + std::to_string(indecies[0]));
for(auto it = indecies.begin()+1; it != indecies.cend(); ++it){
s += (delimiter + tag + std::to_string(*it));
}
return s;
}
(BTW, as for this function concatenate, if indecies is empty, the return value is also an empty string, not exceptions (AndreasDM's one) or UB (Everlight's one).
And if indecies has only a single element, for instance indecies={1}, then result is "Transform#1”, not "Transform#1, ”(YSC's one) or ", Transform#1”(sakra's one).
These are different from other answers and this function will be more simpler if this handling is removed.)
Although the performance may not be a focal point, the above function can be slightly optimized by pre-reserving the minimum capacity to save the resulted string by std::basic_string::reserve as follows.
Here +1 in *.size()+1 means the minimum length of a number character.
I also removed delimiter+tag in the for-loop.
This still looks simple:
DEMO with 5 test cases
std::string concatenate_fast(
const std::vector<int>& indecies,
std::string delimiter = ", ",
const std::string& tag = "Transform#")
{
if(indecies.empty()){
return "";
}
std::string s(tag + std::to_string(indecies[0]));
delimiter += tag;
s.reserve((tag.size()+1) + (indecies.size()-1)*(delimiter.size()+1));
for(auto it = indecies.begin()+1; it != indecies.cend(); ++it){
s += (delimiter + std::to_string(*it));
}
return s;
}
I have also tested the performance of these functions and some proposed answers as follows.
These tests are done by Quick C++ Benchmark within gcc-8.2, C++17 and O3 optimization.
Since std::transform_reduce is still not available in Quick C++ Benchmark, I haven’t tested it.
The above concatenate_fast shows best performance at least in these cases and concatenate is second best.
Finally, just personally, taking the balance of the readability and the performance into account, I would like to propose the above concatenate as a solution:
- Performance test with size 2 and 8. (DEMO)
- Performance test with size 16 and 32. (DEMO)
Unless you have some other requirement to preserve the intermediate tranformed list, storing it is suboptimal. You can just call std::accumulate and do both operations on the fly:
#include <cstdio>
#include <iterator>
#include <numeric>
int main ( )
{
int const input [] = { 1, 2, 3, 4, 5, 6 };
// computes sum of squares
auto const add_square = [] ( int x, int y ) { return x + y * y; };
int result = std::accumulate
( std::cbegin (input)
, std::cend (input)
, 0
, add_square
);
std::printf ( "\n%i\n", result );
return 0;
}
If you have the luxury of using C++17, there is a standard library algorithm which does exactly what you need. Here is an example:
#include <iterator>
#include <iostream>
#include <numeric>
#include <string>
int main()
{
auto input = {1, 2, 3};
std::cout << std::transform_reduce(
std::cbegin(input), std::cend(input),
std::string("Result:"),
[](const std::string & left, const std::string & right) { return left + " " + right; },
[](int value) { return "Transform#" + std::to_string(value); }
) << "\n";
}

Calling a function on every element of a C++ vector

In C++, is there a way to call a function on each element of a vector, without using a loop running over all vector elements? Something similar to a 'map' in Python.
You've already gotten several answers mentioning std::for_each.
While these respond to the question you've asked, I'd add that at least in my experience, std::for_each is about the least useful of the standard algorithms.
I use (for one example) std::transform, which is basically a[i] = f(b[i]); or result[i] = f(a[i], b[i]); much more frequently than std::for_each. Many people frequently use std::for_each to print elements of a collection; for that purpose, std::copy with an std::ostream_iterator as the destination works much better.
Yes: std::for_each.
#include <algorithm> //std::for_each
void foo(int a) {
std::cout << a << "\n";
}
std::vector<int> v;
...
std::for_each(v.begin(), v.end(), &foo);
On C++ 11: You could use a lambda. For example:
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::for_each(nums.begin(), nums.end(), [](int &n){ n++; });
ref: http://en.cppreference.com/w/cpp/algorithm/for_each
If you have C++11, there's an even shorter method: ranged-based for. Its purpose is exactly this.
std::vector<int> v {1,2,3,4,5};
for (int element : v)
std::cout << element; //prints 12345
You can also apply references and const to it as well, when appropriate, or use auto when the type is long.
std::vector<std::vector<int>> v {{1,2,3},{4,5,6}};
for (const auto &vec : v)
{
for (int element : vec)
cout << element;
cout << '\n';
}
Output:
123
456
The OP mentions the map function in Python.
This Python function actually applies a function to every element of a list (or iterable) and returns a list (or iterable) that collects all results.
In other words, it does something like this:
def f( x ) :
""" a function that computes something with x"""
# code here
return y
input = [ x1, x2, x3, ... ]
output = map( func, input )
# output is now [ f(x1), f(x2), f(x3), ...]
Hence, the closest C++ standard-library equivalent to Python's map is actually std::transform (from the <algorithm> header).
Example usage is as follows:
#include <vector>
#include <algorithm>
using namespace std;
double f( int x ) {
// a function that computes the square of x divided by 2.0
return x * x / 2.0 ;
}
int main( ) {
vector<int> input{ 1, 5, 10 , 20};
vector<double> output;
output.resize( input.size() ); // unfortunately this is necessary
std::transform( input.begin(), input.end(), output.begin(), f );
// output now contains { f(1), f(5), f(10), f(20) }
// = { 0.5, 12.5, 50.0, 200.0 }
return 0;
}
Use for_each:
// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void myfunction (int i) {
cout << " " << i;
}
struct myclass {
void operator() (int i) {cout << " " << i;}
} myobject;
int main () {
vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
cout << "myvector contains:";
for_each (myvector.begin(), myvector.end(), myfunction);
// or:
cout << "\nmyvector contains:";
for_each (myvector.begin(), myvector.end(), myobject);
cout << endl;
return 0;
}
You can use std::for_each which takes a pair of iterators and a function or functor.
Thought I would share std::ranges equivalents for for_each and transform, should anyone prefer them:
std::vector<int> v;
std::ranges::for_each(v,[](const auto& n) {});
const auto squared = v | std::views::transform([](const auto& n) { return n*2; });
Running on godbolt: https://godbolt.org/z/zYME6b

How to get an average in C++?

I have an assignment to read a file and output the average test scores.
It is pretty simple but I don't like how the average is done.
average = (test1 + test2 + test3 + test4 + test5) / 5.0;
Is there a way to just have it divide by the number of test scores? I couldn't find anything like this in the book or from google. Something like
average = (test + test + test + test) / ntests;
If you have the values in a vector or an array, just use std::accumulate from <numeric>:
std::vector<double> vec;
// ... fill vec with values (do not use 0; use 0.0)
double average = std::accumulate(vec.begin(), vec.end(), 0.0) / vec.size();
Step 1. Via iteration (if you want to be done) or recursion (if you want to be brave) place all test scores into an array (if you want simplicity and speed) or a linked list (if you want flexibility but slow)
Step 2. Iterate through the array/list until you reach the end; adding the contents of each cell/node as you go. Keep a count of what cell/node you are currently at as you go as well.
Step 3. Take the sum from the first variable and divide it by the second variable that kept track of where you were. This will yield the mean.
Wondering, why no one mentioned boost::accumulators. It is not the shortest of the already posted solutions, but can be more easily extended for more general statistical values. Like standard deviation or higher moments.
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <algorithm>
#include <vector>
double mean(const std::vector<double>& values) {
namespace bo = boost::accumulators;
if (values.empty()) return 0.;
bo::accumulator_set<double, bo::stats<bo::tag::mean>> acc;
acc=std::for_each(values.begin(), values.end(), acc);
return bo::mean(acc);
}
int main()
{
std::vector<double> test = { 2.,6.,4.,7. };
std::cout << "Mean: " << mean(test) << std::endl;
std::cout << "Mean: " << mean({}) << std::endl;
return 0;
}
Here is my generalization of getting the average of the elements of a container by specifying a lambda function to obtain each value and then add up:
template <typename ForwardIterator, typename F>
double inline averageOf (ForwardIterator first, ForwardIterator last, F function) {
std::vector<typename std::result_of<F(typename ForwardIterator::value_type)>::type> values;
while (first != last) {
values.emplace_back (function(*first));
++first;
}
return static_cast<double>(std::accumulate (values.begin(), values.end(), 0)) / values.size();
}
The client code I tested it with goes like
const std::list<CharmedObserver*> devotees =
charmer->getState<CharmerStateBase>(CHARMER)->getDevotees();
const int averageHitPointsOfDevotees = averageOf (devotees.begin(), devotees.end(),
[](const CharmedObserver* x)->int {return x->getCharmedBeing()->getHitPoints();});
C++11 gives nice solution:
constexpr auto countArguments() -> size_t
{
return 0;
}
template<class T1, class ... Ti>
constexpr auto countArguments(T1, Ti ...xi) -> size_t
{
return 1 + countArguments(xi...);
}
template<class T>
constexpr auto sumAruguments(T x) -> double
{
return x;
}
template<class T1, class ... Ti>
constexpr auto sumAruguments(T1 x1, Ti ...xi) -> double // decltype(x1 + sumAruguments(xi...))
{
return x1 + sumAruguments(xi...);
}
template<class...T>
constexpr auto avarage(T...xi) -> double
{
return sumAruguments(xi...) / countArguments(xi...);
}
I was unable to write it so it auto-deduce return type.
When I tried I get weird result for average(-2).
https://wandbox.org/permlink/brssPjggn64lBGVq
You can also calculate average using variable number of arguments. The principle of this a function that an unknown number of arguments is stored in a stack and we can take them.
double average(int n, ...) // where n - count of argument (number)
{
int *p = &n; // get pointer on list of number in stack
p++; // get first number
double *pp = (double *)p; // transformation of the pointer type
double sum = 0;
for ( int i = 0; i < n; pp++, i++ ) //looking all stack
sum+=(*pp); // summarize
return sum/n; //return average
}
And you can using this function like:
double av1 = average( 5, 3.0, 1.5, 5.0, 1.0, 2.0 );
double av2 = average( 2, 3.0, 1.5 );
But the number of arguments must match with the n.

implicit transformation while calling std::adjacent_difference()

I wanted to get a vector of distances between adjacent points in a vector:
struct Point { double x, y, z; }
vector<double> adjacent_distances( vector<Point> points ) {
...
}
I thought that stl::adjacent_difference() would do the trick for me if I simply provided a function that finds the distance between 2 points:
double point_distance( Point a, Point b ) {
return magnitude(a-b); // implementation details are unimportant
}
Thus, I was hoping that this would work,
vector<double> adjacent_distances( vector<Point> points )
{
vector<double> distances;
std::adjacent_difference( points.begin(), points.end(),
std::back_inserter(distances),
ptr_fun( point_distance ) );
return distances;
}
only to find that input and output vectors had to be of (practically) the same type because adjacent_difference() calls
output[0] = input[0]; // forces input and output to be of same value_type
output[1] = op( input[1], input[0] );
output[2] = op( input[2], input[1] );
....
which, sadly, is inconsistent with respect to how std::adjacent_find() works.
So, I had to convert my code to
double magnitude( Point pt );
Point difference( Point a, Point b ); // implements b-a
vector<double> adjacent_distances( vector<Point> points )
{
vector<Point> differences;
std::adjacent_difference( points.begin(), points.end(),
std::back_inserter(differences),
ptr_fun( point_difference ) );
vector<double> distances;
std::transform( differences.begin(), differences.end(),
std::back_inserter(distances),
ptr_fun( magnitude ) );
return distances;
}
NB: the first element of differences had to be removed for the function to behave correctly, but I skipped the implementation details, for brevity.
Question: is there a way I could achieve some transformation implicitly, so that I don't have to create the extra vector, and achieve a call to adjacent_difference() with input_iterator and output_iterator of different value_types ?
Probably this isn't so neat though, in this specific case, std::transform
with 2 input sequences might meet the purpose.
For example:
vector<double> adjacent_distances( vector<Point> points ) {
if ( points.empty() ) return vector<double>();
vector<double> distances(
1, point_distance( *points.begin(), *points.begin() ) );
std::transform( points.begin(), points.end() - 1,
points.begin() + 1,
std::back_inserter(distances),
ptr_fun( point_distance ) );
return distances;
}
Hope this helps
Indeed that adjacent_difference algorithm is logically broken (why should be the difference of the same time of the elements? Why is the first output element equal to the first one instead of getting an output sequence one item shorter than the input one (way more logical)?
Anyway I don't understand why you are punishing yourself by using a functional approach with C++ where clearly the code is going to be harder to write, harder to read, slower to compile and not faster to execute. Oh.. and let's not talk about the kind of joke error message you are going to face if there is any error in what you type.
What is the bad part of
std::vector<double> distances;
for (int i=1,n=points.size(); i<n; i++)
distances.push_back(magnitude(points[i] - points[i-1]));
?
This is shorter, more readable, faster to compile and may be even faster to execute.
EDIT
I wanted to check my subjective "shorter, more readable, faster to compile and may be faster to execute". Here the results:
~/x$ time for i in {1..10}
> do
> g++ -Wall -O2 -o algtest algtest.cpp
> done
real 0m2.001s
user 0m1.680s
sys 0m0.150s
~/x$ time ./algtest
real 0m1.121s
user 0m1.100s
sys 0m0.010s
~/x$ time for i in {1..10}
> do
> g++ -Wall -O2 -o algtest2 algtest2.cpp
> done
real 0m1.651s
user 0m1.230s
sys 0m0.190s
~/x$ time ./algtest2
real 0m0.941s
user 0m0.930s
sys 0m0.000s
~/x$ ls -latr algtest*.cpp
-rw-r--r-- 1 agriffini agriffini 932 2011-11-25 21:44 algtest2.cpp
-rw-r--r-- 1 agriffini agriffini 1231 2011-11-25 21:45 algtest.cpp
~/x$
The following is the accepted solution (I fixed what is clearly a brainfart of passing the vector of points by value).
// ---------------- algtest.cpp -------------
#include <stdio.h>
#include <math.h>
#include <functional>
#include <algorithm>
#include <vector>
using std::vector;
using std::ptr_fun;
struct Point
{
double x, y;
Point(double x, double y) : x(x), y(y)
{
}
Point operator-(const Point& other) const
{
return Point(x - other.x, y - other.y);
}
};
double magnitude(const Point& a)
{
return sqrt(a.x*a.x + a.y*a.y);
}
double point_distance(const Point& a, const Point& b)
{
return magnitude(b - a);
}
vector<double> adjacent_distances( const vector<Point>& points ) {
if ( points.empty() ) return vector<double>();
vector<double> distances(
1, point_distance( *points.begin(), *points.begin() ) );
std::transform( points.begin(), points.end() - 1,
points.begin() + 1,
std::back_inserter(distances),
ptr_fun( point_distance ) );
return distances;
}
int main()
{
std::vector<Point> points;
for (int i=0; i<1000; i++)
points.push_back(Point(100*cos(i*2*3.141592654/1000),
100*sin(i*2*3.141592654/1000)));
for (int i=0; i<100000; i++)
{
adjacent_distances(points);
}
return 0;
}
Here is instead the explicit loop solution; it requires two include less, one function definition less and the function body is also shorter.
// ----------------------- algtest2.cpp -----------------------
#include <stdio.h>
#include <math.h>
#include <vector>
struct Point
{
double x, y;
Point(double x, double y) : x(x), y(y)
{
}
Point operator-(const Point& other) const
{
return Point(x - other.x, y - other.y);
}
};
double magnitude(const Point& a)
{
return sqrt(a.x*a.x + a.y*a.y);
}
std::vector<double> adjacent_distances(const std::vector<Point>& points)
{
std::vector<double> distances;
if (points.size()) distances.reserve(points.size()-1);
for (int i=1,n=points.size(); i<n; i++)
distances.push_back(magnitude(points[i] - points[i-1]));
return distances;
}
int main()
{
std::vector<Point> points;
for (int i=0; i<1000; i++)
points.push_back(Point(100*cos(i*2*3.141592654/1000),
100*sin(i*2*3.141592654/1000)));
for (int i=0; i<100000; i++)
{
adjacent_distances(points);
}
return 0;
}
Summary:
code size is shorter (algtest2.cpp is less than 76% of algtest.cpp)
compile time is better (algtest2.cpp requires less than 83% of algtest.cpp)
execution time is better (algtest2.cpp runs in less than 85% of algtest.cpp)
So apparently on my system (not hand-picked) I was right on all points except execution speed (the one with "maybe") where to get from slightly slower to substantially faster I had to call reserve on the result array. Even with this optimization the code is of course shorter.
I also think that the fact that this version is more readable is also objective and not an opinion... but I'd be happy to be proven wrong by meeting someone that can understand what the functional thing is doing and that cannot understand what the explicit one is doing instead.
Yes, this can be done, but not easily. I don't think it's worth the effort, unless you really need to avoid the copy.
If you really want to do this, you can try creating your own iterator that iterates over the vector<Point> and a wrapper around Point.
The iterator class will dereference to an instance of the wrapper class. The wrapper class should support operator - or your distance function, and it should store the distance. You should then implement an operator for implicit conversion to double, which will be invoked when adjacent_difference attempts to assign the wrapper to the vector<double>.
I don't have time to go into detail, so if anything is unclear, I'll check back later or someone else can try to explain better. Below is an example of a wrapper that does this.
struct Foo {
Foo(double value) { d = value; }
operator double() { return d; }
double d;
};
Foo sub(const Foo& a, const Foo& b) {
return Foo(a.d - b.d);
}
vector<Foo> values = {1, 2, 3, 5, 8};
vector<double> dist;
adjacent_difference(values.begin(), values.end(), back_inserter(dist), sub);
// dist = {1, 1, 1, 2, 3}
This is maybe a bit dirty, but you could simply add
struct Point {
double x,y,z;
operator double() { return 0.0; }
};
or perhaps
struct Point {
double x,y,z;
operator double() { return sqrt(x*x + y*y + z*z); } // or whatever metric you are using
};
The effect being to set the first distance to 0, or the distance of the first point from the origin. However, I could imagine that you wouldn't want to pollute your Point struct with a rather arbitrary definition for conversion to double - in which case dauphic's wrapper is a cleaner solution.
Since you have no use for the first element returned by adjacent_difference, which is precisely the one giving trouble, you can write your own version of the algorithm, skipping that initial assignment:
template <class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator my_adjacent_difference(InputIterator first, InputIterator last,
OutputIterator result,
BinaryOperation binary_op)
{
if (first != last)
{
InputIterator prev = first++; // To start
while (first != last)
{
InputIterator val = first++;
*result++ = binary_op(*val, *prev);
prev = val;
}
}
return result;
}
This should work, though you will be missing some STL optimisations.
I like the a) formulation of the problem, b) comparison of the execution times, c) my_adjacent_difference, d) self-comment that my_adjacent_difference may lack built-in optimizations. I agree that the Standard C++ adjacent_difference logic limits the algorithm's application and that the three lines loop-code is a solution, which many would go with. I reuse the idea to apply the algorithm transform and present the version in C++ 11 illustrating lambdas. Regards.
#include <iostream> /* Standard C++ cout, cerr */
#include <vector> /* Standard C++ vector */
#include <algorithm> /* Standard C++ transform */
#include <iterator> /* Standard C++ back_inserter */
#include <cmath> /* Standard C++ sqrt */
#include <stdexcept> /* Standard C++ exception */
using namespace std; /* Standard C++ namespace */
struct Point {double x, y, z;}; // I would define this differently.
int main(int, char*[])
{
try {
const Point points[] = {{0, 0, 0}, {1, 0, 0}, {1, 0, 3}};
vector<double> distances;
transform(points + 1, points + sizeof(points) / sizeof(Point),
points, back_inserter(distances),
[](const Point& p1, const Point& p2)
{
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
double dz = p2.z - p1.z;
return sqrt(dx * dx + dy * dy + dz * dz);
});
copy(distances.begin(), distances.end(),
ostream_iterator<double>(cout, "\n"));
}
catch(const exception& e) {
cerr << e.what() << endl;
return -1;
}
catch(...) {
cerr << "Unknown exception" << endl;
return -2;
}
return 0;
}
The output:
1
3