Why delete a non-member function? [duplicate] - c++

This question already has an answer here:
What is the point of using delete on a non-member function?
(1 answer)
Closed 4 years ago.
This is about non-member functions. I do understand this as an implementation. But I have a bit of puzzlement with the logic behind?
// why this?
void do_not_use_this_ever ( void ) = delete ;
If I do not want a function to be used, why declare it and then delete it? Why not just:
// why not this?
// void do_not_use_this_ever ( void ) = delete ;
If = delete declares an intent, just a comment like above declares the same intent.
Can anyone think of a use-case where declaring a non-member function as deleted is better then not have it at all?
Update
Already answered here . Although. Both answers use std::cref as an example. As #geza said in the comment to his answer, it would be rather beneficial to discuss other use cases as well.

Deleting a non-member function can be useful to disable a function with certain parameters. For example, here is std::cref:
template< class T >
std::reference_wrapper<const T> cref( const T& t ) noexcept;
template <class T>
void cref(const T&&) = delete;
cref is used to convert an object reference to reference_wrapper. This can be used for example with std::bind: std::bind parameters are copied into the resulting object. But with cref, it becomes just a reference. So, cref must not be used with temporary parameters.
If the second overload wasn't deleted, then for example, cref(2) would be a valid expression (as a temporary can be bound to a const reference). This is a problem, as cref would return a reference to an object which will be destroyed. To disallow this, we need to delete functions where cref is passed a temporary, and this is what the second deleted overload does.

Related

How does std::bind and std::thread copy the arguments that are perfectly forwarded? [duplicate]

This question already has answers here:
move semantics/behaviors in std::bind and std::thread
(1 answer)
Where in the source does gcc's std::bind copy arguments into a data structure?
(2 answers)
Closed 3 months ago.
There is something I miss about std::bind and std::thread. Internally, they both forward the rvalue reference template argument (perfect forwarding). But it is known that it copies the object passed to it, instead we wrapp the lvalue references in std::ref(). If you pass a lvalue like the following:
template <typename T>
void fct(T&& x)
{
f(std::forward(x));
}
...
int r{9};
fct(r);
In this case, r is perfectly forwarded as an lvalue.
So, where does the copy occurs, since in the source code, they always use std::forward?
I understand the reason behind the copying step, but how is it really implemented?
Also, this could help me to understand the use of std::ref in depth.
I thank you in advance for your help.

How do correctly use a callable passed through forwarding reference?

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…

std::forward in non-template function [duplicate]

This question already has answers here:
Usage of std::forward vs std::move
(3 answers)
Closed 5 years ago.
There is some function that has rvalue argument. There is an other function that also has rvalue argument. The first function calls the second function:
void inner(int&& a)
{/* ... */}
void outer(int&& a)
{
inner(std::move(a));
}
I used std::move because we use std::move to pass parameter as rvalue. But my colleague said that std::forward is more appropriate here because we forward (not move) rvalue reference here:
void outer(int&& a)
{
inner(std::forward(a));
}
Is it true? Which variant is more correct?
Forward is a conditional move. Using it here is like saying you should wrap statements in if (true).
The usage of forward is slightly different. It is used like this:
void outer(int&& a)
{
inner(std::forward<int>(a));
}
On non template code, forward is really confusing since there is no forwarding done.
Forwarding exist because of forwarding reference and reference collapsing. Take away those and no more forwarding magic.
In your case you're receiving an rvalue reference. Moving it is the right thing to do.
Forward is conditional move that depends on the declared type of the variable you might want to move. If that variable is an lvalue reference, std::forward<T>(t) won't move it.

Forwarding reference vs const lvalue reference in template code

I've recently been looking into forwarding references in C++ and below is a quick summary of my current understanding of the concept.
Let's say I have a template function footaking a forwarding reference to a single argument of type T.
template<typename T>
void foo(T&& arg);
If I call this function with an lvalue then T will be deduced as T& making the arg parameter be of type T& due to the reference collapsing rules T& && -> T&.
If this function gets called with an unnamed temporary, such as the result of a function call, then Twill be deduced as T making the arg parameter be of type T&&.
Inside foo however, arg is a named parameter so I will need to use std::forward if I want to pass the parameter along to other functions and still maintain its value category.
template<typename T>
void foo(T&& arg)
{
bar(std::forward<T>(arg));
}
As far as I understand the cv-qualifiers are unaffected by this forwarding. This means that if I call foo with a named const variable then T will be deduced as const T& and hence the type of arg will also be const T& due to the reference collapsing rules. For const rvalues T will be deduced as const T and hence arg will be of type const T&&.
This also means that if I modify the value of arg inside foo I will get a compile time error if I did infact pass a const variable to it.
Now onto my question.
Assume I am writing a container class and want to provide a method for inserting objects into my container.
template<typename T>
class Container
{
public:
void insert(T&& obj) { storage[size++] = std::forward<T>(obj); }
private:
T *storage;
std::size_t size;
/* ... */
};
By making the insert member function take a forwarding reference to obj I can use std::forward to take advantage of the move assignment operator of the stored type T if insert was infact passed a temporary object.
Previously, when I didn't know anything about forwarding references I would have written this member function taking a const lvalue reference:
void insert(const T& obj).
The downside of this is that this code does not take advantage of the (presumably more efficient) move assignment operator if insert was passed a temporary object.
Assuming I haven't missed anything.
Is there any reason to provide two overloads for the insert function? One taking a const lvalue reference and one taking a forwarding reference.
void insert(const T& obj);
void insert(T&& obj);
The reason I'm asking is that the reference documentation for std::vectorstates that the push_back method comes in two overloads.
void push_back (const value_type& val);
void push_back (value_type&& val);
Why is the first version (taking a const value_type&) needed?
You have to be careful about function templates, versus non-template methods of class templates. Your member insert is not itself a template. It's a method of a template class.
Container<int> c;
c.insert(...);
We can pretty easily see that T is not deduced on the second line, because it's already fixed to int on the first line, because T is a template parameter of the class, not the method.
Non-template methods of class templates, only differ from regular methods in one way, once the class has been instantiated: they aren't instantiated unless they are actually called. This is useful because it allows a template class to work with types, for which only some of the methods make sense (STL containers are full of examples like this).
The bottom line is that in my example above, since T is fixed to int, your method becomes:
void insert(int&& obj) { storage[size++] = std::forward<int>(obj); }
This is not a forwaring reference at all, but simply takes by rvalue reference, i.e. it only binds to rvalues. That is why you typically see two overloads for things like push_back, one for lvalues and one for rvalues.
#Nir Friedman already answered the question, so I'm going to offer some additional advice.
If your Container class is not meant to store polymorphic types (which is common of containers, including std::vector and other similar STL containers), you can get away with simplifying your code, in the way you're trying to do in your original example.
Instead of:
void insert(T const& t) {
storage[size++] = t;
}
void insert(T && t) {
storage[size++] = std::move(t);
}
You could get perfectly correct code by writing the following instead:
void insert(T t) {
storage[size++] = std::move(t);
}
The reason for this is that if the object is being copied in, t will be copy-constructed with the object provided, and then move-assigned into storage[size++], whereas if the object is being moved in, t will be move-constructed with the object provided, and then move-assigned into storage[size++]. So you've simplified your code at the cost of a single extra move-assignment, which many compilers will happily optimize out.
There is a major downside to this approach, though: If the object defines a copy-constructor and doesn't define a move-constructor (common for older types in legacy code), this results in double-copies in all cases. Your compiler might be able to optimize it away (because compilers can optimize to completely different code so long as the user-visible effects are unchanged), but maybe not. That could be a significant performance hit if you have to work with heavy objects that don't implement move-semantics. This is probably the reason STL containers don't use this technique (they value performance over brevity). But if you're looking for a way to reduce the amount of boilerplate code you write, and aren't worried about having to use "copy-only" objects, then this will probably work fine for you.

Why doesn't std::reference_wrapper implicitly cast to a reference when calling member function? [duplicate]

This question already has answers here:
How to correctly use std::reference_wrappers
(2 answers)
Closed 4 years ago.
I don't understand exactly why one cannot use a std::reference_wrapper like this:
#include <vector>
#include <functional>
struct Foo
{
void f() {};
};
int main()
{
std::vector<std::reference_wrapper<Foo>> vrFoo;
Foo foo;
vrFoo.push_back(foo);
// vrFoo[0].f(); // error
vrFoo[0].get().f(); // or static_cast<Foo&>(v[0]).f();
}
Why do we have to use the get() member function? It looks like std::reference_wrapper has an implicit conversion to T& via operator T&() const noexcept, see http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
so why isn't v[0] implicitly converted to a reference?
In other situations, such as
std::cout << v[0] << std::endl
this conversion takes place (I assume here that Foo overloads operator<<)
Because . is always used to access members of the object it's applied to. Type conversions aren't considered.
There's a proposal to allow overloading of operator., to enable exactly what you want, but that won't be standard until at least C++17, if at all.
This is a language limitation as #MikeSeymour pointed out.
And this is the reason why I think std::reference_wrapper should have an overloaded operator& that returns the address of the wrapped object:
template<class T>
struct reference_wrapper{
...
T* operator &(){return ptr;}
}
So that later one can use &Foo->f() or (*&Foo).f() instead of Foo.get().f() or static_cast<T&>(Foo).f().