Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Standard function objects?

11 views
Skip to first unread message

Alf P. Steinbach

unread,
Dec 22, 2016, 9:56:25 AM12/22/16
to
On 22.12.2016 15:21, Stefan Ram wrote:
> By trial and error I found out that I can multiply as
> follows,
>
> #include <iostream>
> #include <ostream>
> #include <functional>
>
> int main()
> { ::std::cout << ::std::multiplies<>()( 2, 3 )<< '\n'; }

The C++11 standard doesn't specify a default for the template argument
so this is implementation-specific behavior, not guaranteed to compile.

Indeed the following, repeating the standard's definition of
`multiplies`, does not compile with either g++ or MSVC:

#include <iostream>
#include <ostream>

namespace my {
template< class T >
struct multiplies
{
T operator()(const T& x, const T& y) const { return 0; }
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
};
}

int main()
{ ::std::cout << ::my::multiplies<>()( 2, 3 )<< '\n'; }

But amazingly your example code does compile with both g++ and MSVC.


> . Can »multiplies<>()(2,3)« be simplified?
> (Without adding any definitions.)
>
> Why was it designed that way, and not in way that it
> can be used as:
>
> { ::std::cout << ::std::multiplies<>( 2, 3 )<< '\n'; }

It's a type, not an object or function.

And it's a type because sometimes one needs the type, and this was
designed in C++98-times, without a `decltype` operator to produce a type.


> or even
>
> { ::std::cout << ::std::multiplies( 2, 3 )<< '\n'; }
>
> ? I can surely define this myself as
>
> #include <iostream>
> #include <ostream>
>
> template < class T >
> T multiplies( T const l, T const r )
> { return l * r; }
>
> int main()
> { ::std::cout << multiplies( 2, 3 )<< '\n'; }
>
> , and such a function pointer could then also be passed to
> algorithms AFAIK.

The function pointer can be less efficient because with a
`T::operator()` there is only one possibility for the `operator()`, so
inlining can be performed on each call, while with a function pointer
local analysis is not sufficient to say which function it is.

Also the functor approach is more general than a function, e.g. a
functor can carry or refer to state elsewhere, that its result depends on.

Cheers & hth.!,

- Alf

Alf P. Steinbach

unread,
Dec 22, 2016, 3:15:01 PM12/22/16
to
On 22.12.2016 18:29, Stefan Ram wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>> But amazingly your example code does compile with both g++ and MSVC.
>
> I am usually programming against the latest draft, if possible,
> and this contains:
>
> template <class T = void> struct multiplies;
> template <> struct multiplies<void>;
>
> . I never really learned templates, but superficially it
> resembles a default type of »void«.

Oh, I only looked at C++11.

There's so much, I'd call it idiocy, in the C++17 drafts, and will be in
that standard.

And it's not just that it's so meaningless and impractical from the
developer point of view, it's so /arbitrary/, so /unpredictable/,
apparently in support of internal details in some implementation. One
can no longer use common sense to predict what the official language is.
It started for real with C++14 but it's so much worse now.

I apologize for having disinformed you.

I should have qualified very strongly that I was referring to C++11. I
shall strive to do so in the future. Thank you!


Cheers!,

- Alf

0 new messages