I read that function call () can also be overloaded. http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
What would the following mean?
It works.
template<typename T, typename Comp>
struct bind{
T v;
Comp comp;
bool operator()(const T& b){
return comp(b,v);
}
};
int main(){
bind<int, less<int> > b;
b.v = 2;
cout << b(3) << "\n";
}
It means that if you create an object of type bind<>, you can apply the function-call operator to that object.
Like this:
bind<int, std::less<int>> b;
b.v = 2;
std::cout << b(1) << "\n";
That snippet might print "true" on the standard output.
If you have a class called foo, I'm sure you understand what it means to call a member function of an object of that type:
foo f;
f.bar();
You may also understand that you can overload certain operations. For example, you could overload operator+ for foo so that you could do something like this:
foo f, g;
f + g;
Now you can also overload operator() for a class, which allows you to call it as though it were a function:
foo f;
f();
Yes, f is not a function but it is an object of class type that overloads operator(). Class types that do this are known as functors or function objects.
In the example you've given, bind is a functor. When you create an object of that type, you can call it like a function, passing it a const T& and it will return a bool back to you. The implementation of operator() actually calls the function stored in comp, passing it both the T object you passed to operator(), a, and the member object v of type T.
As it stands, it doesn't mean much of anything except "syntax error". For example:
template<T, Op>
This simply isn't allowed. For each template parameter, you need to specify whether it's a type (using class or typename) or a non-type parameter such as an int. Since the apparent intent is that both these should be type parameters, you need something like:
template <class T, class Op>
or:
template <typename T, typename Op>
For this situation, there's no difference in meaning between class and typename.
struct bind{
T v;
Leaving v uninitialized will lead to undefined behavior, so you probably don't want to allow that. You'd normally prevent it by adding a constructor that takes a T as its parameter and initializes v to that value:
bind(T const &v) : v(v) {}
When you include a constructor like this, the compiler won't automatically generate a default constructor, so it's no longer possible to create a bind object with v uninitialized -- exactly what we wanted.
Although creating the comp object:
Op comp;
is fairly harmless, it's also quite unnecessary. You could just as well do the comparison with a temporary instance created with Op(), in which case this:
bool operator()(const T& a){
return comp(a,v);
}
...would become something like this (and the Op comp; simply removed):
bool operator()(T const &a) {
return Op()(a, v);
}
Even with the corrections, I'd consider this code obsolescent. In C++98/03, it would have been useful in a situation where you needed to supply a functor to an algorithm, such as:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
bind<int, std::less<int> >(5));
...which would copy numbers from a to b, removing those less that 5.
In C++11, however, most (if not all) uses of this bind should probably be written as lambdas instead though, so the bit above would become something like:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
[](int x) { return x < 5; });
This is not only shorter, but (at least once you're used to it) quite a bit simpler than using std::less and bind to put together a function. It won't generally make any difference in run-time efficiency -- a lambda is basically a "shorthand" way of generating a class template, so what it generates would end up pretty similar to the code using bind.
Related
I want an object which can wrap a value symantic type and pretend that it is a reference.
Something like this:
int a = 20;
std::list<Wrap<int>> l1;
l1.push_back(a);
std::list<Wrap<int>> l2;
l2.push_back(a);
l2.front() = 10;
cout << l1.front() << endl; // output should be 10
While writing this question it occured to me that a shared_ptr might be what I want. However I am not sure if a pointer symantic object is what I am looking for. Perhaps there is no alternative in the standard library?
std::shared_ptr<int> a = std::make_shared(10);
std::list<std::shared_ptr<int>> l1;
l1.push_back(a);
std::list<std::shared_ptr<int>> l2;
l2.push_back(a);
*(l2.front()) = 20; // not exactly what I wanted to write
cout << *l1.front() << endl; // prints 10
I found std::reference_wrapper but this appears to be the opposite of what I want. It appears to permit a reference type to be used like a value type which is the reverse of what I wanted.
Any thoughts?
Proxy Object
As far as I know, there isn’t such a wrapper in the Standard Library. Fortunately though, you can implement one yourself rather easily.
How to start? Well, we’d like our Wrap<T> to be possibly indistinguishable from a T&. To achieve this, we can implement it as a proxy object. So, we’ll be making a class template storing a T& ref and implement operations one by one:
template<typename T>
struct Wrap
{
private:
T& ref;
public:
// ???
};
Construction
Let’s start with constructors. If we want Wrap<T> to behave like a T& it should be constructible from the same things that T& is constructible. Well then, what is a reference x constructible from?
A non-const lvalue reference like T& x = ...; needs to be constructed from an lvalue of type T. This means that it can be constructed from:
an object of type T
an object of a type derived from T
a different lvalue reference to T
an object convertible to T&
a function call returning T&
A const lvalue reference like const T& x = ...; can also be constructed from a braced-initializer-list or materialized from a temporary, however if we wanted to implement that, then we’d need to actually store a T inside of our class. As such, let’s focus on a non-const reference.
First, let’s implement a constructor from T& which will cover all of the cases shown above:
constexpr Wrap(T& t) noexcept :
ref{t}
{
}
The constructor is constexpr and noexcept because it can be. It is not explicit because we want to be able to use Wrap as transparently as possible.
We need to remember though, that a reference needs to be initializable from a different reference. Because we want our type to behave just like a builtin reference, we need to be able to
initialize a Wrap from a T& (already implemented above)
initialize a Wrap from a different Wrap
initialize a T& from a Wrap
To meet these criteria, we’ll need to implement a conversion operator to T&. If Wrap<T> will be implicitly convertible to T&, then assigning it to a builtin reference will work.
Actually, this:
int x;
Wrap w = x;
Wrap w2 = w;
will also work (ie. w2 will be Wrap<int> rather than a Wrap<Wrap<int>>) because the conversion operator takes precedence.
The implementation of the conversion operator looks like this:
constexpr operator T&() const noexcept
{
return ref;
}
Note that it is constexpr, noexcept and const, but not explicit (just like the constructor).
Miscelaneous operations
Now that we can construct our custom reference wrapper, we’d also like to be able to use it. The natural question is “what can you do with a reference”? Well, builtin references aren’t objects but merely aliases to existing objects. This means that taking the address of the reference actually returns the address of the referent or that you can access members through a reference.
All these things could be implemented, for example by overloading the arrow operator operator-> or the address-of operator operator&. For simplicity though, I will omit implementing these operations and focus only on the most important one: assignment.
Assignment
Firstly, we’d like to be able to assign a Wrap<T> to a T& or a T or basically anything that can be assigned a T. Fortunately, we already got that covered by having implemented the conversion operator.
Now we only need to implement assignment to Wrap<T>. We could be tempted to just write the operator like this:
constexpr T& operator=(const T& t)
{
ref = t;
return ref;
}
constexpr T& operator=(T&& t) noexcept
{
ref = std::move(t);
return ref;
}
Seems fine, right? We have a copy assignment operator and a noexcept move assignment operator. We return a reference as per custom.
Well, the problem is that this implementation is incomplete. The thing is that we don’t check
is T copy-assignable
if it is, then is it nothrow-copy-assignable
is T move-assignable
if it is, then is it nothrow-move-assignable
what is the return type of T’s assignment operator (it could be the customary T&, but it could also theoretically be anything else, like void)
does T have any other assignment operators
This is a lot of cases to cover. Fortunately, we can solve this all by making our assignment operator a template.
Let’s say that the operator will take an object of arbitrary type U as its argument. This will cover both the copy and move assignment operators and any other potential assignment operators. Then, let’s say that the return type of the function will be auto, to let the compiler deduce it. This gives us the following implementation:
template <typename U>
constexpr auto operator=(U u)
{
return (ref = u);
}
Unfortunately though, this implementation is still not complete.
We don’t know if the assignment is noexcept
We don’t distinguish copy assignment and move assignemnt and could potentially be making unnecessary copies.
Is the return type (auto) really correct?
To solve the first issue we can use a conditional noexcept. To check if the assignment operator is noexcept we can either use the type trait std::is_nothrow_assignable_v or the noexcept operator. I think that using the noexcept operator is both shorter and less error-prone, so let’s use that:
template <typename U>
constexpr auto operator=(U u) noexcept(noexcept(ref = u))
{
return (ref = u);
}
To solve the issue of distinguishing copies and moves, instead of taking a U u, we can take a forwarding reference U&& u, to let the compiler deal with all of this. We also need to remember about using std::forward:
template <typename U>
constexpr auto operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return (ref = std::forward<U>(u));
}
There is a bit of code duplication, but, unfortunately, it is inevitable, unless we’d use std::is_nothrow_assignable_v instead.
Finally, is the return type correct? Well, no. Because C++ is C++, parentheses around the returned value actually change its type (ie. return(x); is different from return x;). To return the correct type, we’ll actually also need to apply perfect forwarding to the returned type as well. We can do this by either using a trailing return type or a decltype(auto) return type. I will use decltype(auto) as it’s shorter and avoids duplicating the function body yet again:
template <typename U>
constexpr decltype(auto) operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return ref = std::forward<U>(u);
}
Conclusion
Now, finally, we have a complete implementation. To sum things up, here it is all together (godbolt):
template<typename T>
struct Wrap
{
private:
T& ref;
public:
constexpr Wrap(T& t) noexcept :
ref{t}
{
}
constexpr operator T&() const noexcept
{
return ref;
}
template <typename U>
constexpr decltype(auto) operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return ref = std::forward<U>(u);
}
};
That was quite a bit of C++ type theory to get through to write these 21 lines. Oh, by the way, did I mention value categories...
I'm used to pass lambda functions (and other callables) to template functions -- and use them -- as follows
template <typename F>
auto foo (F && f)
{
// ...
auto x = std::forward<F>(f)(/* some arguments */);
// ...
}
I mean: I'm used to pass them through a forwarding reference and call them passing through std::forward.
Another Stack Overflow user argue (see comments to this answer) that this, calling the functional two or more time, it's dangerous because it's semantically invalid and potentially dangerous (and maybe also Undefined Behavior) when the function is called with a r-value reference.
I've partially misunderstand what he means (my fault) but the remaining doubt is if the following bar() function (with an indubitable multiple std::forward over the same object) it's correct code or it's (maybe only potentially) dangerous.
template <typename F>
auto bar (F && f)
{
using A = typename decltype(std::function{std::forward<F>(f)})::result_type;
std::vector<A> vect;
for ( auto i { 0u }; i < 10u ; ++i )
vect.push_back(std::forward<F>(f)());
return vect;
}
Forward is just a conditional move.
Therefore, to forward the same thing multiple times is, generally speaking, as dangerous as moving from it multiple times.
Unevaluated forwards don't move anything, so those don't count.
Routing through std::function adds a wrinkle: that deduction only works on function pointers and on function objects with a single function call operator that is not && qualified. For these, rvalue and lvalue invocation are always equivalent if both compiles.
I'd say the general rule applies in this case. You're not supposed to do anything with a variable after it was moved/forwarded from, except maybe assigning to it.
Thus...
How do correctly use a callable passed through forwarding reference?
Only forward if you're sure it won't be called again (i.e. on last call, if at all).
If it's never called more than once, there is no reason to not forward.
As for why your snippet could be dangerous, consider following functor:
template <typename T>
struct foo
{
T value;
const T &operator()() const & {return value;}
T &&operator()() && {return std::move(value);}
};
As an optimization, operator() when called on an rvalue allows caller to move from value.
Now, your template wouldn't compile if given this functor (because, as T.C. said, std::function wouldn't be able to determine return type in this case).
But if we changed it a bit:
template <typename A, typename F>
auto bar (F && f)
{
std::vector<A> vect;
for ( auto i { 0u }; i < 10u ; ++i )
vect.push_back(std::forward<F>(f)());
return vect;
}
then it would break spectacularly when given this functor.
If you're either going to just forward the callable to another place or simply call the callable exactly once, I would argue that using std::forward is the correct thing to do in general. As explained here, this will sort of preserve the value category of the callable and allow the "correct" version of a potentially overloaded function call operator to be called.
The problem in the original thread was that the callable was being called in a loop, thus potentially invoked more than once. The concrete example from the other thread was
template <typename F>
auto map(F&& f) const
{
using output_element_type = decltype(f(std::declval<T>()));
auto sequence = std::make_unique<Sequence<output_element_type>>();
for (const T& element : *this)
sequence->push(f(element));
return sequence;
}
Here, I believe that calling std::forward<F>(f)(element) instead of f(element), i.e.,
template <typename F>
auto map(F&& f) const
{
using output_element_type = decltype(std::forward<F>(f)(std::declval<T>()));
auto sequence = std::make_unique<Sequence<output_element_type>>();
for (const T& element : *this)
sequence->push(std::forward<F>(f)(element));
return sequence;
}
would be potentially problematic. As far as my understanding goes, the defining characteristic of an rvalue is that it cannot explicitly be referred to. In particular, there is naturally no way for the same prvalue to be used in an expression more than once (at least I can't think of one). Furthermore, as far as my understanding goes, if you're using std::move or std::forward or whatever other way to obtain an xvalue, even on the same original object, the result will be a new xvalue every time. Thus, there also cannot possibly be a way to refer to the same xvalue more than once. Since the same rvalue cannot be used more than once, I would argue (see also comments underneath this answer) that it would generally be a valid thing for an overloaded function call operator to do something that can only be done once in case the call happens on an rvalue, for example:
class MyFancyCallable
{
public:
void operator () & { /* do some stuff */ }
void operator () && { /* do some stuff in a special way that can only be done once */ }
};
The implementation of MyFancyCallable may assume that a call that would pick the &&-qualified version cannot possibly happen more than once (on the given object). Thus, I would consider forwarding the same callable into more than one call to be semantically broken.
Of course, technically, there is no universal definition of what it actually means to forward or move an object. In the end, it's really up to the implementation of the particular types involved to assign meaning there. Thus, you may simply specify as part of your interface that potential callables passed to your algorithm must be able to deal with being called multiple times on an rvalue that refers to the same object. However, doing so pretty much goes against all the conventions for how the rvalue reference mechanism is generally used in C++, and I don't really see what there possibly would be to be gained from doing this…
I have a library function (not under my control here) which take an r value reference to the movable and copyable type Bar:
void foo(Bar&& b);
In my own code, I sometimes need to give it a copy of an existing value, such as
const auto b = getBar();
foo(mk_copy(b));
b.baz();
This is what comes to mind,
template<typename T> auto mk_copy(T val){return val;}
Is there a standard way to do this, or a more common pattern? Perhaps even
template<typename T> auto mk_copy(T&& val){return std::forward<T>(val);}
Or, as pscill points out just writing the name of the class again,
foo(Bar(b));
but I prefer not to repeat type names.
For the built-in types the prefix + plays the role of “make a copy”:
void foo( char&& ) {}
void bar( double*&& ) {}
auto main() -> int
{
char x{};
foo( +x );
double* p{};
bar( +p );
}
Still, it would probably be confusing to readers of the code if you applied prefix + to some other type, and a general prefix operator+ template might end up in conflict with some class' own prefix operator+.
So, I suggest using the now apparent naming convention for makers, namely a make prefix.
Then it can look like this:
template< class Type >
auto make_copy( Type const& o ) -> Type { return o; }
Your first proposed solution,
template<typename T> auto mk_copy(T val){return val;}
suffers from potentially copying the value twice: first copying to the by-value argument, and then copying to the function result.
This is not a problem for a movable type such as a standard library container, because the return type copying will reduce to a move. But it can be a problem for largish non-movable type, as can occur in legacy code.
The second proposed solution,
template<typename T> auto mk_copy(T&& val){return std::forward<T>(val);}
takes the argument by forwarding reference (a.k.a. universal reference), and then deduces the return type from a re-creation of the argument type. The return type will always be a non-reference, since that's what plain auto deduces, so this is technically correct. But it's needlessly complicated.
There is no standard mechanism, but if you want one, your examples aren't very good. The first mk_copy copies T twice (or copies and moves). The second one seems very confusing as to what it's trying to do.
The obvious way is to simply take a const T&, like you normally would:
template<typename T> T mk_copy(const T &val){return val;}
I think you'd better just define that mk_copy method, or add one more declaration:
auto b_copy = b;
foo(std::move(b_copy));
These are clearer to the readers.
Just to demonstrate the possibilities, you could use decltype to get the type:
foo(std::decay_t<decltype(b)>{b});
or you could get the same effect with lambdas:
foo([&]{return b;}());
or tuples:
foo(std::get<0>(std::make_tuple(b)));
or pairs:
foo(std::make_pair(b, 0).first);
Here's a very simple example:
#include <iostream>
template<typename T>
void DoubleMe(T x) {
x += x;
}
int main()
{
int a = 10;
DoubleMe(a);
std::cout << a; //displays 10 not 20!
}
In cases like this, am I forced to use 'T&' in the function argument instead? Cuz I have read in some tutorials that templates can correctly deduce the appropriate data type, including T*, T[ ], or T& by just defining a simple 'T' before the variable. Help?
You can indeed correctly deduce reference types with plain T. Unfortunately, that does not mean what you think it means.
Given
template <typename T> struct S { };
template <typename T> void f(S<T>) { }
int main() { f(S<int&>{}); }
the type argument for f is correctly deduced as int&.
The problem is that in your case, deducing T as int produces a perfectly valid function already. Perhaps a slight oversimplification, but type deduction produces the simplest T that makes the call work. In your case, T = int makes the call work. Not the way you want it to work, but the compiler can't know that. T = int & would also make the call work, but it's not the simplest T that makes it work.
Maybe this will help you to see it the way the compiler does (apologies to any language lawyers if I am oversimplifying):
In this example, the compiler must infer the type of T to be the type that makes the function declaration legal with the least amount of deduction. Since a T can usually be copy-constructed directly from a const T& (which implies that it can also be copy-constructed from a T&), your function will take a copy.
template<class T>
void foo(T value);
In this example T must be the type of the object thing ref refers to - and since references cannot refer to references, T must be a (possibly const, possibly volatile) type.
template<class T>
void foo(T& ref);
In this example, ref must be referring to a const (possibly volatile) object of type T:
template<class T>
void foo(const T& ref);
In this example, ref may either be a reference or an r-value reference. It's known as a universal reference. You're actually writing two functions in one and it's often the most efficient way to handle the case where you are taking ownership of ref.
template<class T>
void foo(T&& ref);
// called like this:
foo(Bar()); // means ref will be a Bar&&
// called like this:
Bar b;
foo(b); // means ref will be a Bar&
// called like this:
const Bar b;
foo(b); // means ref will be a const Bar&
In summary:
void foo(T value) means I will make a copy of whatever you give me.
void foo(T& value) means I wont make a copy but I may modify your value. You may not give me a temporary.
void foo(const T& value) means I wont make a copy and I cannot modify your copy. You may give me a temporary.
void foo(const T&& value) means I may steal or modify the contents of your value, even if it's a temporary.
Yes, to get the effect you want here, you must add the ampersand.
As you write, templates can correctly deduce data types. However, they cann deduce intent. In this case, the type you pass it is an integer, and it correctly instantiates an integer function that internally doubles the argument passed to it by value. The fact that you meant the function to have a side effect, is not something the compiler can guess.
If you want the function to pass the argument by value, you need to return the value with the same argument type.
T DoubleMe(T x) {
return x + x;
}
I just read somebody call a class with a constructor and an operator() a predicate:
// Example
class Foo {
public:
Foo(Bar);
bool operator()(Baz);
private:
Bar bar;
};
However, I haven't heard the word predicate being used in this context before. I would call such a thing a functor. For me, a predicate would be something from the domain of formal logic.
This raises the following questions:
Is this a common word for something like Foo?
Are both terms used interchangeably, or do they mean slightly different things?
Or
Does the return type (bool versus something else) have something to do with it?
What about the operator() being const?
Functor is a term that refers to an entity that supports operator () in expressions (with zero or more parameters), i.e. something that syntactically behaves as a function. Functor is not necessarily an object of some class with overloaded operator (). Ordinary function names are functors as well. Although in some contexts you can see the term "functor" used in a more narrow and exclusive sense: just class objects, but not ordinary functions.
A predicate is a specific kind of functor: a functor that evaluates to a boolean value. It is not necessarily a value of bool type, but rather a value of any type with "boolean" semantics. The type should be implicitly convertible to bool though.
The shown class is a functor that implements a predicate.
A predicate is a boolean function.
About the operator() being non-const here: it should ideally be const, yes.
A predicate is a special kind of function object. See this excellent column by Nicolai Josuttis. To quote:
A function object that returns a Boolean value is a predicate. That's
what almost all tutorials, books, and manuals write about predicates
of the STL. This, however, is not the whole story.
However, there is an additional requirement that is unfortunately not
mentioned in any manual or in the C++ Standard: A predicate should
always return the same result for the same value.
Or, in the language of C++: You should declare operator() as a
constant member function (and not play games with mutable or casts).
For the same reason, a copy of a predicate should have the same state
as the original.
The reason is that the STL algorithms will copy function objects around, and the copying should not affect the outcome of applying the function objects.
template<typename Arg0>
struct UnaryPredicate
:
public std::function<bool(Arg0 const&)>
{
bool operator()(Arg0 const& a0) const
{
return // your code here
}
};
template<typename Arg0, typename Arg1>
struct BinaryPredicate
:
public std::function<bool(Arg0 const&, Arg1 const&)>
{
bool operator()(Arg const& a0, Arg const& a1) const
{
return // your code here
}
};
As has been said, a predicate is just a user supplied directive to analyze something to a boolean state. So you can have the same two things doing the same thing...
struct is_odd
{
is_odd() : count(0);
bool operartor () (int i) const { ++count; return (i % 2) == 1; }
private
int count;
}
And...
bool isOdd(int i) { return (i % 2) == 1; }
So, what is so special about the functor? It maintains state if you want it to! That means that while these two lines of code do the same thing (assume v is a vector, with values 0 - 9)...
for_each(v.begin(), v.end(), isOdd); //using C-style function pointer
And...
is_odd fn = for_each(v.begin(), v.end(), is_odd); //using functor
Only with the second use case can you then call...
int calls = fn.count;
That is because for_each (as well as other STL algorithm functions) returns the functor it used at the end, so now the final state can be queried.
One other cool thing to note is that in the second case, we are using what is called an "anonymous" object.
From the MSDN:
Represents the method that defines a set of criteria and determines
whether the specified object meets those criteria.
http://msdn.microsoft.com/en-us/library/bfcke1bz.aspx