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
Error: Declaration Does Not Declare Anything
Cost of Using Std::Map with Std::String Keys VS Int Keys
Findwindow Does Not Find the a Window
Are End+1 Iterators for Std::String Allowed
Why Does Gcc Not Seem to Have the Filesystem Standard Library
How to Know When a New Usb Storage Device Is Connected in Qt
C++ Arrays as Function Arguments
What Happens When Calling the Destructor of a Thread Object That Has a Condition Variable Waiting
How to Debug Segmentation Fault
C++11 Random Number Distributions Are Not Consistent Across Platforms -- What Alternatives Are There
After Sending a Lot, My Send() Call Causes My Program to Stall Completely. How Is This Possible
Overloading Postfix and Prefix Operators
Does the Alignas Specifier Work with 'New'
How Is Push_Back Implemented in Stl Vector
Virtual Functions Default Parameters
Absence of Typeof Operator in C++03
Convert Byte Array into Bitset
C++ Error on Ms Visual Studio: "Windows Has Triggered a Breakpoint in Javaw.Exe"