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

Discussion in 'C++' started by Steven T. Hatton, Dec 5, 2004.

  1. 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
     
    Steven T. Hatton, Dec 5, 2004
    #1
    1. Advertising

  2. Steven T. Hatton

    Siemel Naran Guest

    "Steven T. Hatton" <> 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 );
     
    Siemel Naran, Dec 5, 2004
    #2
    1. Advertising

  3. Steven T. Hatton wrote in news: 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/
     
    Rob Williscroft, Dec 5, 2004
    #3
  4. Steven T. Hatton

    Siemel Naran Guest

    "Rob Williscroft" <> 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 );
    }
    };
     
    Siemel Naran, Dec 5, 2004
    #4
  5. Siemel Naran wrote in
    news:u9ysd.1033433$ 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/
     
    Rob Williscroft, Dec 5, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vivi Orunitia
    Replies:
    11
    Views:
    4,544
    Martijn Lievaart
    Feb 4, 2004
  2. Klaas Vantournhout

    f2c's abs conflicts with <complex> abs

    Klaas Vantournhout, Oct 31, 2006, in forum: C++
    Replies:
    3
    Views:
    399
    Victor Bazarov
    Oct 31, 2006
  3. John Doe

    std::abs problem

    John Doe, Mar 19, 2007, in forum: C++
    Replies:
    13
    Views:
    1,246
    P.J. Plauger
    Mar 21, 2007
  4. Philipp Klaus Krause

    multiple definition of `std::abs(long)'

    Philipp Klaus Krause, Jan 25, 2009, in forum: C++
    Replies:
    1
    Views:
    742
    Philipp Klaus Krause
    Jan 25, 2009
  5. Kaba

    std::abs ambiguity

    Kaba, Apr 27, 2009, in forum: C++
    Replies:
    12
    Views:
    1,265
    Christopher Dearlove
    Apr 30, 2009
Loading...

Share This Page