Sign in to follow this  
Graham11

STL binary function

Recommended Posts

Graham11    122
Hi all, I'm having a little problem using the STL function 'adjacent_difference' with my own std::binary_function-derived function. I've created a simple main.cpp (below) to show the problem. When I hit compile I get: error C2440: '=' : cannot convert from 'std::iterator_traits<_Iter>::value_type' to 'std::allocator<_Ty>::value_type' Does anyone know, where have I erred? All the best, Graham
#include <iostream>
#include <deque>
#include <vector>
#include <numeric>
#include <functional>

#include <Wm3Vector3.h>	// http://www.geometrictools.com/Foundation/Math/Wm3Vector3.h

template < class TReal >
class Vec3DistanceBetween : public std::binary_function< Wm3::Vector3< TReal >, Wm3::Vector3< TReal >, TReal >
{
public:
	result_type operator()( const first_argument_type &arg1, const second_argument_type &arg2 ) const
	{
		return ( arg2 - arg1 ).Length();
	}
};

int main()
{
	std::vector< float >::iterator	Iter;
	std::vector< Wm3::Vector3< float > > in;
	std::vector< float > out;
	adjacent_difference( in.begin(), in.end(), out.begin(), Vec3DistanceBetween< float >() );
	return 1;
}

Share this post


Link to post
Share on other sites
Graham11    122
Length returns a templated Real type; the length of a vector. I tried casting the result to 'result_type', but that didn't help ( return (result_type)( arg2 - arg1 ).Length(); )

I looked in <numeric>, and it seems like the line:
for (*_Dest = _Val; ++_First != _Last; )
in _Adjacent_difference is involved, due to it trying to assign *_Dest (which is a Real) with _Val (which is a Vector3). I don't know how to avoid this though; my binary_function's first_argument and second_argument are of different type to my result_type.

Thanks,
Graham

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
the problem could also be in the Length() implementation of yours. Does it work with a difference of two vectors, each being const? When you think "hey! that's the same type! Why isn't there a conversion?".. often const is the "problem".
Make sure your implementation of Length() is const correct.. just a guess, though. You might want to post your Length() method, if you are not sure.

cheers,
simon

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
The problem is probably that adjacent_difference needs to copy the first input element to the output, but has no way to convert a vector to float.

Share this post


Link to post
Share on other sites
Graham11    122
To the first anonymous comment:
The minus operator declaration looks like this:
Vector3 operator- (const Vector3& rkV) const;

and the Length() method is declared:
Real Length () const;

To the second anonymous comment:
This does look like the problem, but how should adjacent_difference() handle such a common situation? I just don't know.

By the way, I'm using Visual Studio 2003 7.1. Maybe I should try another STL implementation such as STLport?

Any suggestions are most welcome.

Ta,
Graham

Share this post


Link to post
Share on other sites
Quote:
Original post by Graham11
To the first anonymous comment:
The minus operator declaration looks like this:
Vector3 operator- (const Vector3& rkV) const;

and the Length() method is declared:
Real Length () const;

To the second anonymous comment:
This does look like the problem, but how should adjacent_difference() handle such a common situation? I just don't know.

By the way, I'm using Visual Studio 2003 7.1. Maybe I should try another STL implementation such as STLport?

Any suggestions are most welcome.

Ta,
Graham


The error you get is correct. From sgi's description of adjacent_difference:
Quote:

Adjacent_difference calculates the differences of adjacent elements in the range [first, last). This is, *first is assigned to *result [1], and, for each iterator i in the range [first + 1, last), the difference of *i and *(i - 1) is assigned to *(result + (i - first)). [2]

(Emphasis is mine).
The type requirements specifically says:
Quote:

InputIterators value type is convertible to a type in OutputIterator's set of value types.

This is obviously not your case (you have no way to convert a Wm::Vector<float> to a float).

For more information here is what the standard says on this issue (26.4.4):
Quote:
Effect: (...) result get the value of *first.
Complexity: exactly (last - first) - 1 application of binary_op

This leads to the same type requirements as in the sgi's explaination.

I'm not sure how to implement what you want. I guess you'll have to implement your own function (not so difficult [smile]).

Regards,

Share this post


Link to post
Share on other sites
Zahlman    1682
He presumably wants the "differences" applied between adjacent pairs of values.

I *think* that binary std::transform can do this for you:


transform(in.begin(), in.end() - 1, in.begin() + 1, out.begin(),
Vec3DistanceBetween< float >());


The SGI doc mentions that the output range can overlap the input range, but seems to be only talking about the unary version, and doesn't say anything about two input ranges overlapping. But as long as your operator is non-mutating, I don't see how it could cause a problem.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this