Why doesn't unary_function define operator()? - c++

I was just looking for a handy base class for a set of functors to be based on taking and int and returning void.
Thinking to use std/functional the functors are basically going to be unary_function<int,void> with operator().
Why is virtual result_type operator()(const argument_type& _Left) const = 0; not defined on the unary_function template? I'm guessing that it's because there could be variations in constness...
Is there some other template I've missed that includes the operator()?
I haven't done this in a while, am I missing something?
How would I also make use of existing functional like
std::ptr_fun< HWND, void >(someFunction);
std::pointer_to_unary_function<HWND, void>(someFunction);
EDIT:
Perhaps I should include the other half of the usage to make this complete. Maybe it's the usage half that is not fitting in with the concept.
How would one pass the functor to a method and use it?
typedef unary_function<int,void> Functor;
void DoStuff(const Functor& functor) {
int demo = 1;
functor(demo);
}
functor as a unary_function doesn't define operator() and so DoStuff doesn't compile.

Template concepts are duck-typed. The fact that a class satisfying the UnaryFunction concept needs operator() is specified in the documentation and inferred from the templates which use template parameters satisfying that concept. There's no need to spell out the function signature, or to require that it be virtual, that it take a const reference parameter, or that it be a const member function.
The unary_function template should not be thought of as an interface (and it isn't designed as one). It's certainly not a polymorphic base class. It's a helper, which is used by classes that wish to implement the AdaptableUnaryFunction concept.
From the STL docs, which are reliable for the original design rationale: "the only reason it exists is to make defining Adaptable Unary Functions more convenient" - http://www.sgi.com/tech/stl/unary_function.html
The standard is similar: "The following classes are provided to simplify the typedefs of the argument and result types" (20.3.1/1)
Advanced usage - actually what's required for UnaryFunction is that if f is a unary function object, and x is convertible to the argument type, then f(x) is a valid expression of the result type. It needn't have a one-argument operator() at all, it's fine to have a two-arg operator() with the second arg having a default value. Try defining that as a pure virtual function ;-)
Second question, you make use of ptr_fun just by calling it with function name/pointer. Its template parameters will be inferred from the function type, so you don't need to specify them. The result is an object of the corresponding pointer_to_unary_function template type.
To use the example straight from the STL docs:
transform(first, last, first,
compose1(negate<double>, ptr_fun(fabs)));
This is approximately equivalent to:
for (auto current = first; current != last; ++current) {
*current = -fabs(*current);
}
(where I use auto in its C++0x sense, meaning "I cannot be bothered / it is impossible to write the iterator type here")
A function name/pointer can be used in transform (which takes a UnaryFunction template parameter), but not in compose1 (which takes an AdapatableUnaryFunction template parameter). So without ptr_fun, there's no way to compose negate with fabs.
In response to your Edit, I stress, unary_function is not a polymorphic base class. You cannot usefully use it (or any of its instantiations) as a function parameter type.
If you want to use the UnaryFunction or AdaptableUnaryFunction concepts, then you must write a function template:
template <typename UnaryFunction>
void DoStuff(UnaryFunction &functor) {
int demo = 1;
functor(demo);
}
This only requires that the functor take a type which int converts to, though. It doesn't require that it take exactly int and return exactly void. That's usually an advantage.
If a template doesn't do what you want, then unary_function is not for you. You haven't missed anything: you can design your own interface with a virtual operator(), but the standard libraries don't aim to provide any such thing.

Because a virtual operator () is not a part of the unary_function concept. The unary function concept can have a non-virtual operator in addition to differences in constness.

Related

Is it possible to determine if a callable is a predicate (i.e. returns bool)?

In an attempt to rewrite a predicate combinator like this
auto constexpr all = [](auto const&... predicates){
return [predicates...](auto const&... x){
return (predicates(x...) && ...);
};
};
(little generalization of this) in a way that it would give meaningful errors when fed with non-predicates/predicates with different arities/arguments, I started writing something like this:
template<typename T, typename = void>
struct IsPredicate : public std::false_type {};
template<typename T>
struct IsPredicate<T, std::enable_if_t<std::is_same_v<bool, return_type_of_callable_T>, void>>
: public std::true_type {};
and then I stared at it for a while... How do I even check what is the return type of a function, if I don't even know how to call it?
I see this:
I couldn't even pass decltype(overloaded_predicate_function) to IsPredicate, because template type deduction can't occur with an overloaded name,
even if I only talk of function objects, the problem of the first bullet point could apply to operator(), in case it is overloaded.
So my question is: is it even possible to determine the return type of an arbitrary callable?
I'm mostly interested in a C++17 answer, but, why not?, I'd also like to know what C++20's concept offer in this respect.
So my question is: is it even possible to determine the return type of an arbitrary callable?
No. You can only do this in very narrow circumstances:
the callable is a pointer to member data / pointer to member function
the callable is a pointer/reference to function
the callable is a function object with a single non-overloaded function call operator that is not a template and no conversion functions to function pointers/reference
That's it. If you have a function object whose call operator is either overloaded or a template, you can't really figure out what its return type is. Its return type could depend on its parameter type, and you may not have a way of knowing what the parameter types could be. Maybe it's a call operator template that only accepts a few specific types that you have no way of knowing about, but it is a predicate for those types?
The best you can do is defer checking until you know what what arguments are. And then C++20 already has the concept for you (predicate):
inline constexpr auto all = []<typename... Ps>(Ps const&... predicates){
return [=]<typename... Xs>(Xs const&... x)
requires (std::predicate<Ps const&, Xs const&...> && ...)
{
return (std::invoke(predicates, x...) && ...);
};
};
Note that you should use std::invoke to allow for pointers to members as predicates as well (and this is what std::predicate checks for).
You cannot determine the return type of a callable without specifying the argument types (usually done by providing actual arguments) because the return type could depend on the argument types. "decltype(potential_predicate)" won't work but "decltype(potential_predicate(args...))" is another matter.
The first will be the type of the callable itself (whether pointer-to-function or a class type or whatever) while the second will produce the return type of the callable expression.
Can't give you a C++17 answer, but since you also asked for concepts:
The requires expression states that the () operator is overloaded and returns a bool. I think a predicate in the classical sense takes two arguments, but the concept can be easily extended to fo fulfill that requirement as well.
template<typename T>
concept IsPredicate =
requires(T a) {
{ a() } -> std::same_as<bool>;
};

How do you define emplace_back and other variadic template functions in a C++ concept?

I'm trying to define a C++ concept for standard library containers that allow push_back/emplace_back:
template <class ContainerType>
concept PushBackContainer = requires(ContainerType a)
{
requires SequenceContainer<ContainerType>;
{ a.push_back(typename ContainerType::const_reference& v) };
{ a.push_back(typename ContainerType::value_type&& v) };
// How do you define a variable templated function:
{ template< class... Args > a.emplace_back(Args&&... args) };
}
The problem I have is how do I define emplace_back with its variadic template arguments? I'm using Visual Studio 2019 but if this isn't supported I'd be interested in the correct syntax come the time it is.
Probably about the best that's worth doing is just a.emplace_back();.
Your push_back requirements don't have a correct syntax, either. I think you want:
template <class ContainerType>
concept PushBackContainer = requires(
ContainerType& a,
typename ContainerType::value_type const& cv,
typename ContainerType::value_type& v)
{
requires SequenceContainer<ContainerType>;
a.push_back(cv);
a.push_back(std::move(v));
a.emplace_back();
};
Requirements don't check for a function signature; they check for the validity of an expression (without instantiating more templates than necessary). If we had a class like:
class StrangeContainer {
public:
using value_type = std::string;
using const_reference = const value_type&;
private:
struct ValueHolder {
ValueHolder(const std::string& s) : value(s) {}
ValueHolder(std::string&& s) : value(std::move(s)) {}
std::string value;
};
public:
void push_back(ValueHolder);
template <typename ... Args>
void emplace_back(Args&&...);
};
then ignoring SequenceContainer requirements, PushBackContainer<StrangeContainer> would be true, and it would also satisfy the Standard's own requirements related to push_back. It satisfies the technical requirements, even though it has some surprising effects like the fact that push_back("") is ill-formed.
So for push_back, we're really just checking that it can be called with a const lvalue and with a non-const rvalue. (The Standard actually also requires that it can be called with a non-const lvalue and with a const rvalue, and these cases have the same behavior as when called with a const lvalue.)
(If you really wanted to test for an exact push_back signature, you could try static_cast<void (ContainerType::*)(typename ContainerType::value_type&&)>(&ContainerType::push_back); - but this is not recommended, since member functions in namespace std are not required to have signatures exactly as described, only to be callable with the same arguments as if declared as described.)
Also, the standard container class templates don't have any constraints on their push_back or emplace_back functions. Every instantiation of the templates which have push_back declares both overloads, whether or not the type is copyable and/or movable. If not, it would be an error to actually call or otherwise odr-use the push_back function, but it "exists" for purposes of requires-expressions and SFINAE contexts. Likewise, the emplace_back member template is declared to accept any number of arguments with any types and value categories, no matter whether they can be used as value_type constructor arguments or not.
So what we would want to test to find out if the container has an emplace_back with an essentially ordinary variadic function declaration would need to be phrased as: Can emplace_back be called with any number of arguments, with each having any possible type and each being either an lvalue or rvalue? I don't think there's any way to really answer that within C++, using requires-expressions, SFINAE tricks, or otherwise. So I would just do one simple test for existence of some sort of emplace_back, and that test might as well be as simple as possible: zero arguments.
You could get fancier and also test for some additional cases: Does emplace_back accept different numbers of arguments, up to some fixed maximum? Does it accept lvalue and rvalue arguments? Does it accept arguments of dummy struct types? Dummy struct types that aren't MoveConstructible? const, volatile, and const volatile types? All possible combinations of all of the above? But since you'll never cover all the cases, how much value does each partial enhancement like this really give, compared to the effort, complexity, and maintenance needed to add checks?

How to deal with variable const in templated code?

I have a class myClass that is templated, and I have it in mind to use it for two particular types.
The trouble is that whether or not something should be const in myClass depends on whether it is instantiated with the first type (in which pretty much everything is const) or the second type (in which pretty much everything is non-const).
How do I solve this problem? It seems there are two possible approaches.
I could write const in the templated code as if it were for the first type (the one that actually is const), and then somehow "throw away" all those consts once I instantiate with the second type? Is this possible?
The second approach is to not write const at all, and then when I instantiate myClass with the first type, I make the entire object itself const. This seems to make up a bit for the lack of const-correctness in the class implementation itself...
Or maybe I can do something else?
EDIT: Wait, no, the last approach wouldn't work, as I then wouldn't be able to call non-const methods....
Let's assume you have these two arbitrary types you want to instantiate your template class with, the first of which should trigger constness for your members:
struct RequiresConst
{};
struct OtherStruct
{};
You can then write some convenience templates like this:
template<class T, bool B>
using conditional_const = typename std::conditional<B, const T, T>::type;
template<class T>
constexpr bool needsConst = std::is_same_v<T, RequiresConst>;
This allows you to naturally spell out what you want:
template<class T>
struct MyClass
{
conditional_const<int, needsConst<T>> member;
};
Demo (including test).
Note that this only works for member variables. I'm not aware of a way to make functions const or non-const in a similarly convenient way. But you could write a const and non-const version for each function and enable exactly one of each pair via std::enable_if (or some other SFINAE).
It should also be mentioned that "this member should be const if the template parameter is this exact class" is a pretty odd requirement - not necessarily wrong but smelly. There is probably some specific trait that class has that you should check instead. But maybe your use case really only ever has the template instantiated for those two classes and the above will be sufficient.
Use a type_traits class.
Start with an empty typetraits class, then specialize it for your first type. Place there all the types you need with the const.
Then specialize it again for your second type, and place there the types without const.
Finally, in your templated class, use the type traits with the template type to select the types you need.

Template functors vs functions

I have been looking at some of the Boost source code and noticed they implement templated functions by using a functor instead of a plain function? Is there a reason for this?
For example:
template<typename Foo, typename Bar>
struct functor {
Bar operator()(const Foo& foo) {
return foo.as_bar();
}
};
as opposed to:
template<typename Foo, typename Bar>
Bar func(const Foo& foo) {
return foo.as_bar();
}
The only advantage I can come up with is it allows classes to inherit the function?
There are two main reasons: The first is, as pythonic metaphor noted, partial specialization is only valid for classes and not functions. Note that functions can use overloads to overcome this problem generally, but often if you are doing metaprogramming it's easier and more generic to use partial specialization. I'd actually think this was the main reason.
The second reason is that anytime that code wants to accept a function object (like in the STL, e.g. std::transform), it will have a type template parameter. If you pass a functor or a lambda, the exact type is known at compile time, and you don't pay for indirection, and inlining can be performed. If you pass a function pointer (or a std::function), only the signature is known at compile time, and you pay for an indirection (and you can't inline). For instance, std::sort can be considerably faster with a functor than a function pointer.
Note that there is a little used feature called function pointer template parameters; these are non type template parameters that specialize on a specific function, and thus can remove indirection. However, if you use one of these, you can't use a functor at all. So most code that wants to accepts a function object does it the way I described above.

Generic lambdas Vs Standard template functions (What to use and When)

Generic Lambdas are a way of defining lambdas that read as follows:
auto identity = [](auto a){return a;}
Compare this with:
template <typename T>
T Identity(T t){return t;}
or with
template <typename T>
struct Identity { T operator()(T a) { return a; } };
This is my understanding
lambdas allow context capture using [&], [=], etc, I am not sure how this will be used / applied in generic lambdas. Is this the main difference ?
generic lambdas can be cast to function pointers whereas, template specialisation can be cast to function pointers.
A simple real world example will be useful to understand what to use and when.
[Appended] Here is the generic lambda proposal : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3559.pdf
Pretty much like lambdas, generic lambdas are defined through equivalence to an implicitly defined function object (where non-generic lambdas have the additional ability that with empty capture they can convert to a function pointer). The only real difference between generic and non-generic lambdas is that generic lambda have call operator which is a function template while it is a non-template for non-generic lambdas.
For generic lambdas the conversion to function pointers doesn't exist (see 5.1.2 [expr.prim.lambda] paragraph 6).
Since generic lambdas are still objects with a call operator, they can be used directly as an argument where a generic function objects can be used. That is not the case for a function templates: these behave more like an overload set and you need to get the instantiated before you can pass them as a function object.
Although you can't get a pointer to a function template, you can get a pointer to a function template specialization (as #Columbo pointed out in a comment, a function template specialization is a function). You can't get a pointer to a function out of a generic lambda.
Function templates participate in overload resolution while function objects don't really participate: when an object is found during name look-up this object is chosen even if there could be functions found with the same name and with a nice match for overloading. This implies, that these two are not equivalent:
template <typename T>
auto identity(T value) { return value; }
auto identity = [](auto value) { return value; }
The second implementation hijacks the name while the former is used as a candidate in overload resolution.
Aside from auxiliary objects created from within a function I would use generic lambdas for functions which are not meant as customization points (e.g. it would be nice if standard library algorithms were such objects). The main benefit is that function objects can be readily adapted, e.g., using std::bind() which is not true for function templates.