Why Have Unary_Function, Binary_Function Been Removed from C++11

Why have unary_function, binary_function been removed from C++11?

It isn't removed, it's just deprecated in C++11. It's still part of the C++11 standard. You can still use it in your own code. It was removed in C++17 though.

It isn't used in the standard any more because requiring implementations to derive from binary_function is over-specification.

Users should not care whether less derives from binary_function, they only need to care that it defines first_argument_type, second_argument_type and result_type. It should be up to the implementation how it provides those typedefs.

Forcing the implementation to derive from a specific type means that users might start relying on that derivation, which makes no sense and is not useful.

Edit

How can we improve this in c++11 without unary_function?

You don't need it.

template<typename adaptableFunction>
class unary_negate
{
private:
adaptableFunction fun_;
public:
unary_negate(const adaptableFunction& f):fun_(f){}

template<typename T>
auto operator()(const T& x) -> decltype(!fun_(x))
{
return !fun_(x);
}
}

In fact you can do even better, see not_fn: a generalized negator

What is an equivalent replacement for std::unary_function in C++17?

std::unary_function and many other base classes such as std::not1 or std::binary_function or std::iterator have been gradually deprecated and removed from the standard library, because there is no need for them.

In modern C++, concepts are being used instead. It is not relevant whether a class inherits specifically from std::unary_function, it just matters that it has a call operator which takes one argument. This is what makes it a unary function. You would detect this by using traits such as std::is_invocable in combination with SFINAE or requires in C++20.

In your example, you can simply remove the inheritance from std::unary_function:

struct path_sep_comp
{
// also note the removed default constructor, we don't need that

// we can make this constexpr in C++17
constexpr bool operator () (tchar ch) const
{
#if defined (_WIN32)
return ch == LOG4CPLUS_TEXT ('\\') || ch == LOG4CPLUS_TEXT ('/');
#else
return ch == LOG4CPLUS_TEXT ('/');
#endif
}
};

replacement for std::binary_function

First, my advice is to watch CppCon 2015: Stephan T. Lavavej "functional: What's New, And Proper Usage". std::binary_function is mentioned on slide 36, at around 36 mins in the video. You can find the slides at github.com/CppCon/CppCon2015). It doesn't go into detail why you shouldn't use std::binary_function, but if you're using something that's been deprecated since C++11, then you would probably benefit from watching it.

If you want the actual rationale for not using it, try n4190:

unary_function/binary_function were useful helpers when C++98-era
adaptors needed argument_type/etc. typedefs. Such typedefs are
unnecessary given C++11's perfect forwarding, decltype, and so forth.
(And they're inapplicable to overloaded/templated function call
operators.) Even if a class wants to provide these typedefs for
backwards compatibility, it can do so directly (at a minor cost in
verbosity) instead of inheriting from unary_function/binary_function,
which is what the Standard itself started doing when these helpers
were deprecated.

Now you simply don't need it, so you can remove all traces of it from your program.

In C++14, transparent comparators were added. But it can be implemented in C++11. Just specialize it for void:

template<>
struct absoluteLess<void> {
template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
-> decltype(absolute(std::forward<T>(lhs)) < absolute(std::forward<U>(rhs)))
{
return absolute(std::forward<T>(lhs)) < absolute(std::forward<U>(rhs));
}
}
};

Now the type can be deduced:

std::max_element(v.begin(), v.end(), absoluteLess<>());

How do I replace std::binary_function with something else without pain?

I don't know any existing types in standard library, but it's not a big deal to create your own:

template<class Arg1, class Arg2, class Result> 
struct binary_function
{
using first_argument_type = Arg1;
using second_argument_type = Arg2;
using result_type = Result;
};

template <typename ArgumentType, typename ResultType>
struct unary_function
{
using argument_type = ArgumentType;
using result_type = ResultType;
};

Both of these classes are just simple base classes for user-defined functional objects, e.g.:

struct MyFuncObj : std::unary_function<int, bool>
{
bool operator()(int arg) { ... }
};

Having aliases for arguments allowed to use some standard library built in functionality, e.g. std::not1: std::not1(MyFuncObj()).

My guess why this was deprecated is because after C++11 mostly lambdas are used to create functional objects. And having variadic templates it's quite easy to create generic version of not and other things without having std::not1, std::not2.

Why does `std::unary_function` still compile in c++17?

Since it's no longer part of the C++17 standard its inclusion in one of your source code files falls into the same category as code that introduces things into std.

In other words, the program behaviour is undefined.

The program working is a manifestation of that undefined behaviour. And perhaps your implementation defines that undefined behaviour. But even so, your code is not portable C++17.

What do we need unary_function and binary_function for?

These aren't functions, these are classes (structs, actually, but doesn't matter). When you define your own binary functions to use with STL algorithms, you derive them from these classes in order to automatically get all the typedefs.

E.g.

struct SomeFancyUnaryFunction: public std::unary_function<Arg_t, Result_t>
{
Result_t operator ()(Arg_t const &)
{
...
}
};

now you don't need to manually provide the typedefs for argument_type, result_type etc. These structs, just like the iterator struct are there just for our convenience, in order to reuse the typedefs needed for algorithms.

Update for C++11:

As of C++11, the new std::bind does not really need any typedefs, so there are, in a way, obsolete.



Related Topics



Leave a reply



Submit