I want an utility to transform a std::tuple<T,U> to std::pair<T,U>, while leaving a std::tuple<T, U, V, W...> unchanged.
Furthermore, I want this utility to
be a function object, not a function, so that I can pass it around as I like;
enforce that it's input must be a std::tuple;
taking advantage of move semantics whenever it is possible to do so and it makes sense.
The last point is the difficult part, for me, and it's the reason I'm asking this question.
I know that tuples can store values as well as references (lvalue references as well as rvalue references), so imagine that the sought function, if fed with an rvalue 2-tuple, it could steal resources from the non-reference components, but should leave intact the reference component.
For instance given
A a;
B b;
std::tuple<A, B&> t{a,b};
where I know a is copied in the tuple, while b is not, I think that doing
auto p{to_pair(t)};
should result in a std::pair<A, B&> which holds another copy of a and a reference to the only b that exists so far.
On the other hand, doing
B b;
auto p{to_pair(std::tuple<A, B&>{A{},b})};
should result again in a std::pair<A, B&>, but this would hold the very A{} of which no copy should ever be made; and it would hold a reference to b anyway.
The scenario described above is already enough for me to be in doubt about what to do, let alone thinking of other combinations of &/const&/&&.
Some time ago I had a hard time answering a question about std::tuples and perfect forwarding, but I can never say I've understood them fully.
template<class...Fs>
struct overloaded : Fs... {
using Fs::operator()...;
};
template<class...Fs>
overloaded(Fs&&...)->overloaded<std::decay_t<Fs>...>;
auto move_tuples = []<class...Ts>(std::tuple<Ts...> x){return std::move(x);};
auto to_pair = []<class A, class B>(std::tuple<A, B> x){
return std::pair<A,B>( std::get<0>(std::move(x)), std::get<1>(std::move(x)) );
};
auto your_function = overloaded{move_tuples, to_pair};
I think that is what you want.
I take the arguments by value, then move them to the return value. If they are values, the result is that the contained values are moved. If they are references, they aren't, the references are just propagated.
The get<N> "does the right thing" when passed an rvalue tuple. If returns an rvalue from a value.
In c++17 you'll have to replace the lambdas with manual structs.
Or write two normal overloads, and
auto obj=[](auto&&x)->decltype(normal_func(decltype(x)(x))){return decltype(x)(x);};
to turn the overloaded function call normal_func into a single function object.
Related
When creating local variables, is it correct to use (const) auto& or auto?
e.g.:
SomeClass object;
const auto result = object.SomeMethod();
or const auto& result = object.SomeMethod();
Where SomeMethod() returns a non-primitive value - maybe another user-defined type.
My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Does this also apply to range based for loops?
for(const auto& object : objects)
auto and auto && cover most of the cases:
Use auto when you need a local copy. This will never produce a reference. The copy (or move) constructor must exist, but it might not get called, due to the copy elision optimization.
Use auto && when you don't care if the object is local or not. Technically, this will always produce a reference, but if the initializer is a temporary (e.g., the function returns by value), it will behave essentially like your own local object.
Also, auto && doesn't guarantee that the object will be modifiable, either. Given a const object or reference, it will deduce const. However, modifiability is often assumed, given the specific context.
auto & and auto const & are a little more specific:
auto & guarantees that you are sharing the variable with something else. It is always a reference and never to a temporary.
auto const & is like auto &&, but provides read-only access.
What about for primitive/non-primitive types?
There is no difference.
Does this also apply to range based for loops?
Yes. Applying the above principles,
Use auto && for the ability to modify and discard values of the sequence within the loop. (That is, unless the container provides a read-only view, such as std::initializer_list, in which case it will be effectively an auto const &.)
Use auto & to modify the values of the sequence in a meaningful way.
Use auto const & for read-only access.
Use auto to work with (modifiable) copies.
You also mention auto const with no reference. This works, but it's not very commonly used because there is seldom an advantage to read-only access to something that you already own.
Yes, it is correct to use auto and auto& for local variables.
When getting the return type of a function, it is also correct to use auto&. This applies for range based for loops as well.
General rules for using auto are:
Choose auto x when you want to work with copies.
Choose auto &x when you want to work with original items and may modify them.
Choose auto const &x when you want to work with original items and will
not modify them.
You can read more about the auto specifier here.
auto uses the same mechanism of type deduction as templates, the only exception that I am aware of being that of brace-init lists, which are deduced by auto as std::initializer_list, but non-deduced in a template context.
auto x = expression;
works by first stripping all reference and cv qualifiers from the type of the right hand side expression, then matching the type. For example, if you have const int& f(){...} then auto x = f(); deduces x as int, and not const int&.
The other form,
auto& x = expression
does not strip the cv-qualifiers, so, using the example above, auto& x = f() deduces x as const int&. The other combinations just add cv qualifiers.
If you want your type to be always deduced with cv-ref qualifiers, use the infamous decltype(auto) in C++14, which uses the decltype type deduction rules.
So, in a nutshell, if you want copies, use auto, if you want references, use auto&. Use const whenever you want additional const-ness.
EDIT
There is an additional use case,
auto&& x = expression;
which uses the reference-collapsing rules, same as in the case of forwarding references in template code. If expression is a lvalue, then x is a lvalue reference with the cv-qualifiers of expression. If expression is a rvalue, then x is a rvalue reference.
When creating local variables, is it correct to use (const) auto& or auto?
Yes. The auto is nothing more than a compiler-deduced type, so use references where you would normally use references, and local (automatic) copies where you would normally use local copies. Whether or not to use a reference is independent of type deduction.
Where SomeMethod() returns a non-primitive value - maybe another user-defined type. My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
Legal? Yes, with the const. Best practice? Probably not, no. At least, not with C++11. Especially not, if the value returned from SomeMethod() is already a temporary. You'll want to learn about C++11 move semantics, copy elision, and return value optimization:
https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by-value/
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199
https://isocpp.org/wiki/faq/ctors#return-by-value-optimization
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Yes, this is fine.
Does this also apply to range based for loops?
for(const auto& object : objects)
Yes, this is also fine. I write this sort of code at work all the time.
When creating local variables, is it correct to use (const) auto& or auto?
e.g.:
SomeClass object;
const auto result = object.SomeMethod();
or const auto& result = object.SomeMethod();
Where SomeMethod() returns a non-primitive value - maybe another user-defined type.
My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Does this also apply to range based for loops?
for(const auto& object : objects)
auto and auto && cover most of the cases:
Use auto when you need a local copy. This will never produce a reference. The copy (or move) constructor must exist, but it might not get called, due to the copy elision optimization.
Use auto && when you don't care if the object is local or not. Technically, this will always produce a reference, but if the initializer is a temporary (e.g., the function returns by value), it will behave essentially like your own local object.
Also, auto && doesn't guarantee that the object will be modifiable, either. Given a const object or reference, it will deduce const. However, modifiability is often assumed, given the specific context.
auto & and auto const & are a little more specific:
auto & guarantees that you are sharing the variable with something else. It is always a reference and never to a temporary.
auto const & is like auto &&, but provides read-only access.
What about for primitive/non-primitive types?
There is no difference.
Does this also apply to range based for loops?
Yes. Applying the above principles,
Use auto && for the ability to modify and discard values of the sequence within the loop. (That is, unless the container provides a read-only view, such as std::initializer_list, in which case it will be effectively an auto const &.)
Use auto & to modify the values of the sequence in a meaningful way.
Use auto const & for read-only access.
Use auto to work with (modifiable) copies.
You also mention auto const with no reference. This works, but it's not very commonly used because there is seldom an advantage to read-only access to something that you already own.
Yes, it is correct to use auto and auto& for local variables.
When getting the return type of a function, it is also correct to use auto&. This applies for range based for loops as well.
General rules for using auto are:
Choose auto x when you want to work with copies.
Choose auto &x when you want to work with original items and may modify them.
Choose auto const &x when you want to work with original items and will
not modify them.
You can read more about the auto specifier here.
auto uses the same mechanism of type deduction as templates, the only exception that I am aware of being that of brace-init lists, which are deduced by auto as std::initializer_list, but non-deduced in a template context.
auto x = expression;
works by first stripping all reference and cv qualifiers from the type of the right hand side expression, then matching the type. For example, if you have const int& f(){...} then auto x = f(); deduces x as int, and not const int&.
The other form,
auto& x = expression
does not strip the cv-qualifiers, so, using the example above, auto& x = f() deduces x as const int&. The other combinations just add cv qualifiers.
If you want your type to be always deduced with cv-ref qualifiers, use the infamous decltype(auto) in C++14, which uses the decltype type deduction rules.
So, in a nutshell, if you want copies, use auto, if you want references, use auto&. Use const whenever you want additional const-ness.
EDIT
There is an additional use case,
auto&& x = expression;
which uses the reference-collapsing rules, same as in the case of forwarding references in template code. If expression is a lvalue, then x is a lvalue reference with the cv-qualifiers of expression. If expression is a rvalue, then x is a rvalue reference.
When creating local variables, is it correct to use (const) auto& or auto?
Yes. The auto is nothing more than a compiler-deduced type, so use references where you would normally use references, and local (automatic) copies where you would normally use local copies. Whether or not to use a reference is independent of type deduction.
Where SomeMethod() returns a non-primitive value - maybe another user-defined type. My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
Legal? Yes, with the const. Best practice? Probably not, no. At least, not with C++11. Especially not, if the value returned from SomeMethod() is already a temporary. You'll want to learn about C++11 move semantics, copy elision, and return value optimization:
https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by-value/
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199
https://isocpp.org/wiki/faq/ctors#return-by-value-optimization
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Yes, this is fine.
Does this also apply to range based for loops?
for(const auto& object : objects)
Yes, this is also fine. I write this sort of code at work all the time.
I can see why the auto type in C++11 improves correctness and maintainability. I've read that it can also improve performance (Almost Always Auto by Herb Sutter), but I miss a good explanation.
How can auto improve performance?
Can anyone give an example?
auto can aid performance by avoiding silent implicit conversions. An example I find compelling is the following.
std::map<Key, Val> m;
// ...
for (std::pair<Key, Val> const& item : m) {
// do stuff
}
See the bug? Here we are, thinking we're elegantly taking every item in the map by const reference and using the new range-for expression to make our intent clear, but actually we're copying every element. This is because std::map<Key, Val>::value_type is std::pair<const Key, Val>, not std::pair<Key, Val>. Thus, when we (implicitly) have:
std::pair<Key, Val> const& item = *iter;
Instead of taking a reference to an existing object and leaving it at that, we have to do a type conversion. You are allowed to take a const reference to an object (or temporary) of a different type as long as there is an implicit conversion available, e.g.:
int const& i = 2.0; // perfectly OK
The type conversion is an allowed implicit conversion for the same reason you can convert a const Key to a Key, but we have to construct a temporary of the new type in order to allow for that. Thus, effectively our loop does:
std::pair<Key, Val> __tmp = *iter; // construct a temporary of the correct type
std::pair<Key, Val> const& item = __tmp; // then, take a reference to it
(Of course, there isn't actually a __tmp object, it's just there for illustration, in reality the unnamed temporary is just bound to item for its lifetime).
Just changing to:
for (auto const& item : m) {
// do stuff
}
just saved us a ton of copies - now the referenced type matches the initializer type, so no temporary or conversion is necessary, we can just do a direct reference.
Because auto deduces the type of the initializing expression, there is no type conversion involved. Combined with templated algorithms, this means that you can get a more direct computation than if you were to make up a type yourself – especially when you are dealing with expressions whose type you cannot name!
A typical example comes from (ab)using std::function:
std::function<bool(T, T)> cmp1 = std::bind(f, _2, 10, _1); // bad
auto cmp2 = std::bind(f, _2, 10, _1); // good
auto cmp3 = [](T a, T b){ return f(b, 10, a); }; // also good
std::stable_partition(begin(x), end(x), cmp?);
With cmp2 and cmp3, the entire algorithm can inline the comparison call, whereas if you construct a std::function object, not only can the call not be inlined, but you also have to go through the polymorphic lookup in the type-erased interior of the function wrapper.
Another variant on this theme is that you can say:
auto && f = MakeAThing();
This is always a reference, bound to the value of the function call expression, and never constructs any additional objects. If you didn't know the returned value's type, you might be forced to construct a new object (perhaps as a temporary) via something like T && f = MakeAThing(). (Moreover, auto && even works when the return type is not movable and the return value is a prvalue.)
There are two categories.
auto can avoid type erasure. There are unnamable types (like lambdas), and almost unnamable types (like the result of std::bind or other expression-template like things).
Without auto, you end up having to type erase the data down to something like std::function. Type erasure has costs.
std::function<void()> task1 = []{std::cout << "hello";};
auto task2 = []{std::cout << " world\n";};
task1 has type erasure overhead -- a possible heap allocation, difficulty inlining it, and virtual function table invocation overhead. task2 has none. Lambdas need auto or other forms of type deduction to store without type erasure; other types can be so complex that they only need it in practice.
Second, you can get types wrong. In some cases, the wrong type will work seemingly perfectly, but will cause a copy.
Foo const& f = expression();
will compile if expression() returns Bar const& or Bar or even Bar&, where Foo can be constructed from Bar. A temporary Foo will be created, then bound to f, and its lifetime will be extended until f goes away.
The programmer may have meant Bar const& f and not intended to make a copy there, but a copy is made regardless.
The most common example is the type of *std::map<A,B>::const_iterator, which is std::pair<A const, B> const& not std::pair<A,B> const&, but the error is a category of errors that silently cost performance. You can construct a std::pair<A, B> from a std::pair<const A, B>. (The key on a map is const, because editing it is a bad idea)
Both #Barry and #KerrekSB first illustrated these two principles in their answers. This is simply an attempt to highlight the two issues in one answer, with wording that aims at the problem rather than being example-centric.
The existing three answers give examples where using auto helps “makes it less likely to unintentionally pessimize” effectively making it "improve performance".
There is a flip side to the the coin. Using auto with objects that have operators that don't return the basic object can result in incorrect (still compilable and runable) code. For example, this question asks how using auto gave different (incorrect) results using the Eigen library, i.e. the following lines
const auto resAuto = Ha + Vector3(0.,0.,j * 2.567);
const Vector3 resVector3 = Ha + Vector3(0.,0.,j * 2.567);
std::cout << "resAuto = " << resAuto <<std::endl;
std::cout << "resVector3 = " << resVector3 <<std::endl;
resulted in different output. Admittedly, this is mostly due to Eigens lazy evaluation, but that code is/should be transparent to the (library) user.
While performance hasn't been greatly affected here, using auto to avoid unintentional pessimization might be classified as premature optimization, or at least wrong ;).
When creating local variables, is it correct to use (const) auto& or auto?
e.g.:
SomeClass object;
const auto result = object.SomeMethod();
or const auto& result = object.SomeMethod();
Where SomeMethod() returns a non-primitive value - maybe another user-defined type.
My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Does this also apply to range based for loops?
for(const auto& object : objects)
auto and auto && cover most of the cases:
Use auto when you need a local copy. This will never produce a reference. The copy (or move) constructor must exist, but it might not get called, due to the copy elision optimization.
Use auto && when you don't care if the object is local or not. Technically, this will always produce a reference, but if the initializer is a temporary (e.g., the function returns by value), it will behave essentially like your own local object.
Also, auto && doesn't guarantee that the object will be modifiable, either. Given a const object or reference, it will deduce const. However, modifiability is often assumed, given the specific context.
auto & and auto const & are a little more specific:
auto & guarantees that you are sharing the variable with something else. It is always a reference and never to a temporary.
auto const & is like auto &&, but provides read-only access.
What about for primitive/non-primitive types?
There is no difference.
Does this also apply to range based for loops?
Yes. Applying the above principles,
Use auto && for the ability to modify and discard values of the sequence within the loop. (That is, unless the container provides a read-only view, such as std::initializer_list, in which case it will be effectively an auto const &.)
Use auto & to modify the values of the sequence in a meaningful way.
Use auto const & for read-only access.
Use auto to work with (modifiable) copies.
You also mention auto const with no reference. This works, but it's not very commonly used because there is seldom an advantage to read-only access to something that you already own.
Yes, it is correct to use auto and auto& for local variables.
When getting the return type of a function, it is also correct to use auto&. This applies for range based for loops as well.
General rules for using auto are:
Choose auto x when you want to work with copies.
Choose auto &x when you want to work with original items and may modify them.
Choose auto const &x when you want to work with original items and will
not modify them.
You can read more about the auto specifier here.
auto uses the same mechanism of type deduction as templates, the only exception that I am aware of being that of brace-init lists, which are deduced by auto as std::initializer_list, but non-deduced in a template context.
auto x = expression;
works by first stripping all reference and cv qualifiers from the type of the right hand side expression, then matching the type. For example, if you have const int& f(){...} then auto x = f(); deduces x as int, and not const int&.
The other form,
auto& x = expression
does not strip the cv-qualifiers, so, using the example above, auto& x = f() deduces x as const int&. The other combinations just add cv qualifiers.
If you want your type to be always deduced with cv-ref qualifiers, use the infamous decltype(auto) in C++14, which uses the decltype type deduction rules.
So, in a nutshell, if you want copies, use auto, if you want references, use auto&. Use const whenever you want additional const-ness.
EDIT
There is an additional use case,
auto&& x = expression;
which uses the reference-collapsing rules, same as in the case of forwarding references in template code. If expression is a lvalue, then x is a lvalue reference with the cv-qualifiers of expression. If expression is a rvalue, then x is a rvalue reference.
When creating local variables, is it correct to use (const) auto& or auto?
Yes. The auto is nothing more than a compiler-deduced type, so use references where you would normally use references, and local (automatic) copies where you would normally use local copies. Whether or not to use a reference is independent of type deduction.
Where SomeMethod() returns a non-primitive value - maybe another user-defined type. My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
Legal? Yes, with the const. Best practice? Probably not, no. At least, not with C++11. Especially not, if the value returned from SomeMethod() is already a temporary. You'll want to learn about C++11 move semantics, copy elision, and return value optimization:
https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by-value/
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199
https://isocpp.org/wiki/faq/ctors#return-by-value-optimization
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Yes, this is fine.
Does this also apply to range based for loops?
for(const auto& object : objects)
Yes, this is also fine. I write this sort of code at work all the time.
I have a function f that accepts a vector of pointers. Once the function f finishes, these pointers are no longer valid. Note, there is no real need to change the vector itself, I just want to encourage callers not to use the pointers after the call to f. There are three possible signatures for f:
The move signature
void f(vector<void*> &&v); // because the pointers in v are no longer valid.
// This signature also allows me to have f call clear() on v.
The const signature
void f(const vector<void*> &v); // because the pointers in v are no longer valid,
// but we don't have to change the vector v.
The pointer signature
void f(vector<void*> *v); // The functino modifies v in a predictable way
// (it clears it). A pointer is used instead of a reference so that
// calls to the function will have a '&' which clearly shows to the reader
// that this function modifies its argument. '*' is different from '&&' since '&&'
// may imply "do not use v, but it is unknown how it will be modified" while
// '*' implies a clear semantic for how v is changed.
Which signature is more idiomatic to use in C++11?
How about
void f(vector<void*> v);
And to use it:
vector<void*> myVec = /*...*/;
f(std::move(myVec));
If f logically needs ownership of a vector, this is the idiomatic way. It allows the caller to decide whether to move or copy a vector to f.
If the caller actually wants f to modify his vector (so the vector is actually an in/out argument) then this doesn't suit your needs. However in/out arguments suck. Functions should take input as arguments and return output as a return value. That's what god intended.
If you really want to do this with the type system, it is always possible to encode extra information using your own type.
template<class T>
struct invalidates_contained_pointers;
template<class T>
invalidates_contained_pointers<T>* contents_will_be_invalidated(T* ptr) {
return reinterpret_cast<invalidates_contained_pointers<T>*>(ptr);
}
void f(invalidates_contained_pointers<vector<void*>> *v){
auto pv = reinterpret_cast<vector<void*> *>(v);
// ...
}
f(contents_will_be_invalidated(&vec));
A similar approach can be used for references.
The short answer: there is no way to do this. The only thing that is 'official' is the inverse: there is a signature that promises that a function f(..) will NOT change its arguments: the const keyword.
Typically one adheres to the following:
functions that do not modify their arguments either get their arguments as copy-by-value or mark their arguments explicitly with const
arguments that are passed by non-const reference, move or pointer to non-const object should be read as "there is a fair chance this argument is modified by the called function f(...)".
As others have said, the type system doesn't allow you to indicate something like "don't use this data after this function call". What you could do:
void f(vector<void*> &v)
{
// ... use v ...
v.clear(); // encourage callers not to use the pointers after the call
}
f should clear the vector if it is deleting the pointers (or freeing whatever they are handles to). It is just pointlessly dangerous to leave the caller with a vector of intederminate values.
So f should accept the vector by non-const reference. Whether you want to make this lvalue reference or rvalue reference is up to you; but the lvalue version seems simpler.
Out of those three: vector<void*> * requires an lvalue to take the address of. const vector<void*> & allows either lvalues or rvalues to be passed in. vector<void*> && only allows rvalues to be passed in.
Based on your question, your function makes sense to be called with either lvalues or rvalues, so const vector<void*> & is the obvious choice.
There is no way to indicate through the type system that the caller should stop using the contained pointers, and you shouldn't try to indicate that through the type system. Indicate that through the documentation.