Benefits of using reference_wrapper instead of raw pointer in containers? - c++

What benefits has using std::reference_wrapper as template parameter of containers instead of raw pointers? That is std::vector<std::reference_wrapper<MyClass> > vs. std::vector<MyClass*>
I like forgetting about nulls and not having to use pointer syntax, but the verbosity of the types (i.e. vector<reference_wrapper<MyClass> >) plus having the call site use std::ref to wrap the actual reference makes me think it is not worth it.
I am referring to cases in which using std::shared_ptr or any other smart pointer is not an option.
Are there other benefits of using reference_wrapper or any other factors I am currently not taking into account? (I think my question applies to both C++11's reference_wrapper and boost's)

I don't think there is any technical difference. Reference wrapper provides basic pointer functionality, including the ability to change the target dynamically.
One benefit is that it demonstrates intent. It tells people who read the code that "whoever" has the variable, isn't actually controlling its lifespan. The user hasn't forgotten to delete or new anything, which some people may start to look for when they see pointer semantics.

C references are really problematic while working with templates. If you are "lucky" enough to compile code with reference as a template parameter you might have problems with code that would work (for some reason) as follows:
template<class T> f(T x) { g(x); }
template<class T> g(T x) { x++; }
Then even if you call f<int&>(x) it will call g<int>. But reference_wrapper works fine with templates.
As also mentioned earlier - you will have problems with compiling things like vector<int&>, but vector<reference_wrapper<int>> works fine.

Related

Is it still possible to customize STL vector's "reference" type?

Is it possible to customize the reference of a std::vector.
Until C++11 it seemed to be possible through the Allocator template parameter.
But not anymore?
According to the documentation, http://en.cppreference.com/w/cpp/container/vector, reference is now always value_type and value_type is always the template parameter T.
It seems to be impossible even using allocator_traits,
http://en.cppreference.com/w/cpp/memory/allocator_traits
Is there a workaround for this?
If not, does it means that I have to specialize the entire std::vector and probably reproduce all its functionality if I want to have a special reference type based on the allocator?
If this is so, generally speaking what is the logic for all these constrains? To force the user to use std::vector<T, A> to always manage regular memory (in which, value_type = T, reference = T& and pointer = T*?)
Note: I am aware of the std::vector<bool> controversy. However this a bit more general because in principle I need a custom std::vector<RegularType, special_allocator<RegularType>> mainly to control the return type of operator[](int) to a special proxy object.
Specific implementation: I am looking at GCC 6.3.1's stdlib source and in std_vector.h one can read:
template<typename _Tp, ...>
class vector : ...{
...
public:
typedef typename _Alloc_traits::reference reference;
};
which seems to indicate that it is still possible to specify a reference type via the allocator (_traits?).
According to the documentation, allocator or the allocator_traits doesn't need to have a reference type.
Plus, I don't know how to customize this type anyway.
Is GCC not following the standard? Or is it simply that indirectly allocator_traits<Allocator>::reference is forced to be allocator_traits<Allocator>::value_type&?
If this is so, generally speaking what is the logic for all these constrains?
The purpose is to stop promising things C++ cannot deliver.
Back in the C++98/03 days, it was thought that proxy types, specialized references and the like could really work with standard library containers and algorithms. By the time C++11 rolled around, it had become abundantly clear that... no, they really can't. Or at least, not with the same semantics as an actual language reference.
With that wisdom in mind, C++11 removed a lot of these no-longer-reasonable customization points. The typedefs were left in, but mainly for backwards-compatibility's sake.
which seems to indicate that it is still possible to specify a reference type via the allocator (_traits?).
No, it isn't. This is a bug in libstdc++; reference is required to be value_type& for containers now. allocator_traits has no reference customization point.

Modifying scoped enum by reference

I am increasingly finding scoped enums unwieldy to use. I am trying to write a set of function overloads including a template for scoped enums that sets/initializes a value by reference--something like this:
void set_value(int& val);
void set_value(double& val);
template <typename ENUM> set_value(ENUM& val);
However, I don't quite see how to write the templated version of set_value without introducing multiple temporary values:
template <typename ENUM>
set_value(ENUM& val)
{
std::underlying_type_t<ENUM> raw_val;
set_value(raw_val); // Calls the appropriate "primitive" overload
val = static_cast<ENUM>(raw_val);
}
I believe the static_cast introduces a second temporary value in addition to raw_val. I suppose it's possible that one or both of these could be optimized away by the compiler, and in any case it shouldn't really make much difference in terms of performance since the set_value call will also generate temporary values (assuming it's not inlined), but this still seems inelegant. What I would like to do would be something like this:
template <typename ENUM>
set_value(ENUM& val)
{
set_value(static_cast<std::underlying_type_t<ENUM>&>(val));
}
... but this isn't valid (nor is the corresponding code using pointers directly instead of references) because scoped enums aren't related to their underlying primitives via inheritance.
I could use reinterpret_cast, which, from some preliminary testing, appears to work (and I can't think of any reason why it wouldn't work), but that seems to be frowned upon in C++.
Is there a "standard" way to do this?
I could use reinterpret_cast, which, from some preliminary testing, appears to work (and I can't think of any reason why it wouldn't work), but that seems to be frowned upon in C++.
Indeed, that reinterpret_cast is undefined behavior by violation of the strict aliasing rule.
Eliminating a single mov instruction (or otherwise, more or less, copying a register's worth of data) is premature micro-optimization. The compiler is likely to be able to take care of it.
If performance is really important, then follow the optimization process: profile, disassemble, understand the compiler's interpretation, and work together with it within the defined rules.
At a glance, you (and the compiler) might have an easier time with functions like T get_value() instead of void set_value(T). The flow of data and initialization make more sense, although type deduction is lost. You can regain the deduction through tag types, if that's really important.

Mock the std::move() function to assess its performance impact

I would like to "mock" the std::move() function to assess its (positive) performance impact on a C++ library I have written.
I have used std::move() extensively and I would like to avoid grepping everywhere to remove it. What is the best way to replace it with an identity function? I'm compiling with gcc.
This should "work" but it's actually undefined behaviour:
// Standard library includes must be above.
#define move not_a_move
namespace std {
template<typename T>
typename std::remove_lvalue_reference<T>::type const&
not_a_move(T&& x)
{
return x;
}
}
This won't capture implicit moves or moves done inside the standard library itself. I would recommend just removing all your uses of std::move; it's cleaner and actually allowed. :P
I'm fairly certain there is no way to achieve this short of massacring your own code to remove all the move constructors on the large objects you're wanting to profile. You may also find you would then have problems with passing non rvalue references to functions expecting rvalue references.
So I would suggest not bothering and accept that it's highly likely your code is faster and be satisfied with that.
I actually wanted to try this a year or so ago, and never found a way.

Variadic function declaration VS a function taking a list

While designing a class or a function, which way, that is shown below, is better and why?
class Container {
//Provide this functionality??
void addItemVariadic(const Value& val, ...);
//Or provide this functionality??
void addItemList(const list<Value>& vals);
};
Is it better to provide a function like addItemVariadic(..), or addItemList(..)?
Or is it better to provide a set of such functions, like further taking some iterators, or is it better to limit the functionality, like just taking a list?
Using variadic functions is dangerous
If you ever pass a variable which has not the appriopriate type, it will crash at run time, when calling the function.
On the contrary if you use a std::list, it won't compile simply, and you avoid a crash.
Btw: I advice you to use std::vector instead of std::list in this case.
Edit1 Possible Dupplicate Question. with a nice solution using operator << to inputs all the parameters in one shot.
Edit2 So as to choose between different std::containers, there is a choose-graph as answer to this question. This graph addresses at C++03, it doesn't cover the new containers introduced in C++1.

Why does allocator in c++ provide specialization for type void

I notice that the allocator in c++ provides specialization for type void. Is there any special purpose to do this? It doesn't make sense to allocate memory for void type, right?
This old Standard Librarian column by Matt Austern has a fairly thorough discussion of allocators in general, including this tidbit:
What do we do about void? Sometimes a container has to refer to void
pointers, and the rebind mechanism almost gives us what we need, but
not quite. It doesn't work, because we would need to write something
like malloc_allocator::pointer, and we've defined
malloc_allocator in such a way that instantiating it for void would be
illegal. It uses sizeof(T), and it refers to T&; neither is legal when
T is void. The solution is as simple as the problem: specialize
malloc_allocator for void, leaving out everything except the bare
minimum that we need for referring to void pointers.
malloc_allocator is the sample implementation that Austern uses in his example, but it holds true for the general case.
The allocator needs to be specialized for void because you cannot have references to void.