Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > std::transform container => std::abs(container)

Reply
Thread Tools

std::transform container => std::abs(container)

 
 
Steven T. Hatton
Guest
Posts: n/a
 
      12-05-2004
This code works for dividing each element of a boost::array<> by a value of
its element type:

template <typename T, size_t S>
inline boost::array<T, S>& operator/=( boost::array<T, S>& lhs, const T&
rhs ) {
std::transform( lhs.begin()
, lhs.end()
, lhs.begin()
, std::bind2nd( std::divides<T>(), rhs ) );
return lhs;
}

I want to use std::transform in a similar fashion to set each element of a
boost::array<> to the result of applying std::abs() to it.

The result can easily be obtained with this code:

template <typename T, size_t Order_S>
inline boost::array<T, Order_S>& abs( boost::array<T, Order_S>& v ) {
for ( size_t i = 0; i < v.size(); i++ ) {
v[ i ] = std::abs( v[ i ] );
}
return v;
}

I would like to know how to apply a function such as std::abs in a way
similar to the use of std::bind2nd ( std::divides<T>(), rhs ) in the above
example. How can this be done?

--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell

 
Reply With Quote
 
 
 
 
Siemel Naran
Guest
Posts: n/a
 
      12-05-2004
"Steven T. Hatton" <(E-Mail Removed)> wrote in message

> std::transform( lhs.begin()
> , lhs.end()
> , lhs.begin()
> , std::bind2nd( std::divides<T>(), rhs ) );


> I want to use std::transform in a similar fashion to set each element of a
> boost::array<> to the result of applying std::abs() to it.


Here is one way

int (*absolute)(int) = &std::abs;
std::transform(lhs.begin()
, lhs.end()
, lhs.begin()
, absolute );



 
Reply With Quote
 
 
 
 
Rob Williscroft
Guest
Posts: n/a
 
      12-05-2004
Steven T. Hatton wrote in news:(E-Mail Removed) in
comp.lang.c++:

> This code works for dividing each element of a boost::array<> by a
> value of its element type:
>
> template <typename T, size_t S>
> inline boost::array<T, S>& operator/=( boost::array<T, S>& lhs,
> const T&
> rhs ) {
> std::transform( lhs.begin()
> , lhs.end()
> , lhs.begin()
> , std::bind2nd( std::divides<T>(), rhs ) );
> return lhs;
> }
>
> I want to use std::transform in a similar fashion to set each element
> of a boost::array<> to the result of applying std::abs() to it.
>
> The result can easily be obtained with this code:
>
> template <typename T, size_t Order_S>
> inline boost::array<T, Order_S>& abs( boost::array<T, Order_S>& v
> ) {
> for ( size_t i = 0; i < v.size(); i++ ) {
> v[ i ] = std::abs( v[ i ] );
> }
> return v;
> }
>
> I would like to know how to apply a function such as std::abs in a way
> similar to the use of std::bind2nd ( std::divides<T>(), rhs ) in the
> above example. How can this be done?
>


Write you're own functor:

template < typename T > struct my_abs
{
typedef T return_type;

T operator () ( T const &arg ) const
{
return std::abs( arg );

/* or even better (ADL friendly version):
*/
using std::abs;
return abs( arg );
}
};

The other alternative is to put a cast into the call to
std::transform:

std::transform(
lhs.begin(), lhs.end(), lhs.begin(),
static_cast< T (*)(T) >( std::abs )
);


The disadvantage here is that for T = short (for example) there
is no overload short std::abs( short ), so the static_cast can't
succeed. Also Argument Dependant Lookup (ADL) can't be used.

Remember to include <cstdlib> and <cmath> so that you get all the
overloads of std::abs, also unless you use an ADL friendly functor
you'll need to include <complex> before calling std::abs if you want
your code to work with std::complex (this also applies valarray).

Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
Siemel Naran
Guest
Posts: n/a
 
      12-05-2004
"Rob Williscroft" <(E-Mail Removed)> wrote in message

> template < typename T > struct my_abs
> {
> typedef T return_type;
>
> T operator () ( T const &arg ) const
> {
> return std::abs( arg );
>
> /* or even better (ADL friendly version):
> */
> using std::abs;
> return abs( arg );
> }
> };


The standard typedef names are result_type and argument_type. These allow
compatibility with other standard binders in STL and boost like
std::bind2nd.

template < typename T > struct my_abs
{
typedef T argument_type;
typedef T result_type;
T operator () ( T const &arg ) const
{
using std::abs;
return abs( arg );
}
};

My preferred way is to derive from std::unary_function<argument_type,
result_type>.

template < typename T > struct my_abs : std::unary_function<T, T>
{
T operator () ( T const &arg ) const
{
using std::abs;
return abs( arg );
}
};



 
Reply With Quote
 
Rob Williscroft
Guest
Posts: n/a
 
      12-05-2004
Siemel Naran wrote in
news:u9ysd.1033433$(E-Mail Removed) in
comp.lang.c++:

>
> The standard typedef names are result_type


Thanks I always get this wrong.

> and argument_type.


AIUI (I haven't researched this myself, just going on snippets
from usenet) argument_type isn't needed (used).

> These
> allow compatibility with other standard binders in STL and boost like
> std::bind2nd.
>
> template < typename T > struct my_abs
> {
> typedef T argument_type;
> typedef T result_type;
> T operator () ( T const &arg ) const
> {
> using std::abs;
> return abs( arg );
> }
> };
>
> My preferred way is to derive from std::unary_function<argument_type,
> result_type>.


Yep, but that does add an extra byte to the function object in some
cases:

struct my_functor : std::binary_function< int, int, bool >
{
std::less< int > m_less;
// operator here ...
};

The above has 2 subobjects of type std::binary_function< int, int, bool >
so EBO (Empty Base (class) Optimization) can't happen.

I am perhapse being needlessly pedantic (and possibly I'm premeturly
optimizing), OTOH typing "typedef T result_type;" is shorter (and IMO
less cryptic) than writing " : std::unary_function< T, T > ".

If only I could remember result_type not return_type all would be
well .

Either way I have to lookup result_type or binary_function /
unary_function as I'm actualy not sure the bool return type above
shouldn't be the first argument.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
container within a container issue: set in the map puzzlecracker C++ 8 09-21-2008 11:08 PM
container inside container in stl wolverine C++ 2 07-24-2006 03:08 PM
Copy elements from one STL container to another STL container Marko.Cain.23@gmail.com C++ 4 02-16-2006 05:03 PM
STL: container's values setup by another container Maitre Bart C++ 2 02-11-2004 12:11 AM
std::container::iterator vs std::container::pointer Vivi Orunitia C++ 11 02-04-2004 08:09 AM



Advertisments