I want to store a reference to an object in a boost::any object. How do I initialize the boost::any object? I tried std::ref(), but boost::any gets initialized with std::reference_wrapper<>. For example, the following
#include <boost/any.hpp>
#include <cxxabi.h>
#include <iostream>
int main(void)
{
int s;
int i = 0;
boost::any x(std::ref(i));
std::cout << abi::__cxa_demangle(x.type().name(), 0, 0, &s) << "\n";
return 0;
}
prints
std::reference_wrapper<int>
I want the boost::any to contain int& instead.
The boost::any class doesn't have an interface allowing something like this: you would need to specify the type of the reference with the constructor. I don't think that you can explicitly specify the type of templated constructor because I don't see any place you could stick it. Even if you can explicitly specify the template parameter, it wouldn't work in C++2003 bcause there is no reference collapsing available and the parameter is declared as taking a T const&: you'd be trying to create a T& const& which won't fly.
I think your best option is to either use std::reference_wrapper<T> if you insist on something looking remotely reference like or just to use T*.
That said, it would be generally possible to have a templatized static factor method of a type similar to boost::any which would be used to explicitly specify the template argument. However, since boost::any is deliberately designed to deal with value types this isn't done. I'm a bit dubious whether it should be done as well: using a pointer is perfectly good alternative. If you really need a reference type you'll probably have to implement it yourself.
The behaviour is correct, expected and appropriate. std::ref is a helper function that creates an object of type std::reference_wrapper<T>, and the reference wrapper is a class with value semantics that holds a reference -- that's exactly the sort of thing you want to put into a container if you want the container to track outside references.
So just go with the solution you have.
If you will, you cannot have a container of direct, naked references, much like you cannot have an array of references. The wrapper is designed precisely to accommodate such needs.
Related
Let's take the following function declaration:
void print(SomeType const* i);
Here, the const* nature of the argument i suggest the intent, that the parameter is optional, since it may be nullptr. If this was not intended, the argument would instead just be a const&. Communicating optional-semantics were certainly not the original intent for designing pointers, but using them to do so happens to work just fine for a long time.
Now, since using raw pointers is generally discouraged in modern C++ (and should be avoided in favor of std::unique_ptr and std::shared_ptr to precisely indicate particular ownership-semantics), I wonder how to properly indicate function parameters' optional-semantics without passing by value, i. e. copying, as
void print(std::optional<SomeType> i);
would do.
After thinking about it for a while I came up with the idea of using:
void print(std::optional<SomeType const&> i);
This would in fact be most precise. But it turns out that std::optional cannot have reference types.¹
Also, using
void print(std::optional<SomeType> const& i);
would in no way be optimal, since then we would require our SomeType to exists in an std::optional on the caller-side, again possibly (or rather likely) requiring a copy there.
Question: So what would be a nice modern approach for allowing optional arguments without copying? Is using a raw pointer here still a reasonable approach in modern C++?
¹: Ironically the depicted reason for why std::optional cannot have reference types (controversy about rebinding or forwarding on assignment) does not apply in the case of std::optionals of const references, since they cannot be assigned to.
Accepting a raw pointer is perfectly fine and is still done in plenty of "modern" codebases (which I'll note is a fast-moving target). Just put a comment on the function saying that it's allowed to be null and whether the function holds a copy of the pointer after the call (i.e. what are the lifetime requirements for the pointed-to value).
Does function overloading provide a clean solution here? E.g. To declare both the const ref and empty param list versions of the function?
This may depend on what the function body does in the no argument/null case - and how you can manage the two implementations to minimize code overlap.
Raw pointers are usually fine for this type of optional argument passing, actually one of the only times it is fine to use raw pointers overall. This is also the canonical recommended way.
That being said, boost::optional does allow you to use reference optional and const reference optionals. It was decided against to have this feature in the std library (for reasons I leave out here).
This is actually what std::reference_wrapper was made for. Also see Does it make sense to combine optional with reference_wrapper? for more reasoning as to when to use it, and when not to use it.
Here, the const* nature of the argument i suggest the intent, that the parameter is optional since it may be nullptr.
[...]
So what would be a nice modern approach for allowing optional arguments without copying?
Allowing an optional argument (not in the std::optional sense, but in the semantic sense) with differing implementation variations based on whether the optional argument is present or not sound like an ideal candidate for overloading:
struct SomeType { int value; };
namespace detail {
void my_print_impl(const SomeType& i) {
std::cout << i.value;
}
} // namespace detail
void my_print() {
const SomeType default_i{42};
detail::my_print_impl(default_i);
}
void my_print(const SomeType& i) {
detail::my_print_impl(i);
}
or
namespace detail {
void my_print_impl() {
std::cout << "always print me\n";
}
} // namespace detail
void my_print() {
detail::my_print_impl();
}
void my_print(const SomeType& i) {
detail::my_print_impl();
std::cout << "have some type: " << i.value;
}
or some similar variation, depending on what your implementation should do depending on the existence/non-existence of the optional argument.
Optional references, otherwise, are basically raw pointers, and the latter may just as well be used (if overloading is not applicable).
I have a class which accumulates information about a set of objects, and can act as either a functor or an output iterator. This allows me to do things like:
std::vector<Foo> v;
Foo const x = std::for_each(v.begin(), v.end(), Joiner<Foo>());
and
Foo const x = std::copy(v.begin(), v.end(), Joiner<Foo>());
Now, in theory, the compiler should be able to use the copy elision and return-value optimizations so that only a single Joiner object needs to be created. In practice, however, the function makes a copy on which to operate and then copies that back to the result, even in fully-optimized builds.
If I create the functor as an lvalue, the compiler creates two extra copies instead of one:
Joiner<Foo> joiner;
Foo const x = std::copy(v.begin(), v.end(), joiner);
If I awkwardly force the template type to a reference it passes in a reference, but then makes a copy of it anyway and returns a dangling reference to the (now-destroyed) temporary copy:
x = std::copy<Container::const_iterator, Joiner<Foo>&>(...));
I can make the copies cheap by using a reference to the state rather than the state itself in the functor in the style of std::inserter, leading to something like this:
Foo output;
std::copy(v.begin(), v.end(), Joiner<Foo>(output));
But this makes it impossible to use the "functional" style of immutable objects, and just generally isn't as nice.
Is there some way to encourage the compiler to elide the temporary copies, or make it pass a reference all the way through and return that same reference?
You have stumbled upon an often complained about behavior with <algorithm>. There are no restrictions on what they can do with the functor, so the answer to your question is no: there is no way to encourage the compiler to elide the copies. It's not (always) the compiler, it's the library implementation. They just like to pass around functors by value (think of std::sort doing a qsort, passing in the functor by value to recursive calls, etc).
You have also stumbled upon the exact solution everyone uses: have a functor keep a reference to the state, so all copies refer to the same state when this is desired.
I found this ironic:
But this makes it impossible to use the "functional" style of immutable objects, and just generally isn't as nice.
...since this whole question is predicated on you having a complicated stateful functor, where creating copies is problematic. If you were using "functional" style immutable objects this would be a non-issue - the extra copies wouldn't be a problem, would they?
If you have a recent compiler (At least Visual Studio 2008 SP1 or GCC 4.4 I think) you can use std::ref/std::cref
#include <string>
#include <vector>
#include <functional> // for std::cref
#include <algorithm>
#include <iostream>
template <typename T>
class SuperHeavyFunctor
{
std::vector<char> v500mo;
//ban copy
SuperHeavyFunctor(const SuperHeavyFunctor&);
SuperHeavyFunctor& operator=(const SuperHeavyFunctor&);
public:
SuperHeavyFunctor():v500mo(500*1024*1024){}
void operator()(const T& t) const { std::cout << t << std::endl; }
};
int main()
{
std::vector<std::string> v; v.push_back("Hello"); v.push_back("world");
std::for_each(v.begin(), v.end(), std::cref(SuperHeavyFunctor<std::string>()));
return 0;
}
Edit : Actually, the MSVC10's implementation of reference_wrapper don't seem to known how to deduce the return type of function object operator(). I had to derive SuperHeavyFunctor from std::unary_function<T, void> to make it work.
Just a quick note, for_each, accumulate, transform (2nd form), provide no order guarantee when traversing the provided range.
This makes sense for implementers to provide mulit-threaded/concurrent versions of these functions.
Hence it is reasonable that the algorithm be able to provide an equivalent instance (a new copy) of the functor passed in.
Be wary when making stateful functors.
RVO is just that -- return value optimization. Most compilers, today, have this turned-on by default. However, argument passing is not returning a value. You possibly cannot expect one optimization to fit in everywhere.
Refer to conditions for copy elision is defined clearly in 12.8, para 15, item 3.
when a temporary class object that has
not been bound to a reference (12.2)
would be copied to a class object with
the same cv-unqualified type, the copy
operation can be omitted by
constructing the temporary object
directly into the target of the
omitted copy
[emphasis mine]
The LHS Foo is const qualified, the temporary is not. IMHO, this precludes the possibility of copy-elision.
For a solution that will work with pre-c++11 code, you may consider using boost::function along with boost::ref(as boost::reference_wrapper alone doesn't has an overloaded operator(), unlike std::reference_wrapper which indeed does). From this page http://www.boost.org/doc/libs/1_55_0/doc/html/function/tutorial.html#idp95780904, you can double wrap your functor inside a boost::ref then a boost::function object. I tried that solution and it worked flawlessly.
For c++11, you can just go with std::ref and it'll do the job.
I have been looking at vector implementations and stumbled upon a line that confuses me as a naive C++ learner.
What is T*& return type?
Is this merely a reference to a pointer?
Why would this be useful then?
link to code: https://github.com/questor/eastl/blob/56beffd7184d4d1b3deb6929f1a1cdbb4fd794fd/vector.h#L146
T*& internalCapacityPtr() EASTL_NOEXCEPT { return mCapacityAllocator.first(); }
It's a reference-to-a-pointer to a value of type T which is passed as a template argument, or rather:
There exists an instance of VectorBase<T> where T is specified by the program, T could be int, string or anything.
The T value exists as an item inside the vector.
A pointer to the item can be created: T* pointer = &this->itemValues[123]
You can then create a reference to this pointer: https://msdn.microsoft.com/en-us/library/1sf8shae.aspx?f=255&MSPPError=-2147217396
Correct
If you need to use a value "indirectly" then references-to-pointers are cheaper to use than pointer-to-pointers as the compiler/CPU doesn't need to perform a double-indirection.
http://c-faq.com/decl/spiral.anderson.html
This would be a reference to a pointer of type T. References to pointers can be a bit tricky but are used a lot with smart pointers when using a reference saves an increment to the reference counter.
Types in C++ should be read from right to left. Following this, it becomes a: Reference to a pointer of T. So your assumption is correct.
References to pointers are very useful, this is often used as an output argument or an in-out argument. Let's consider a specific case of std::swap
template <typename T>
void swap(T*& lhs, T*& rhs) {
T *tmp = rhs;
rhs = lhs;
lhs = tmp;
}
As with every type, it can be used as return value. In the state library, you can find this return type for std::vector<int *>::operator[], allowing v[0] = nullptr.
On the projects that I've worked on, I haven't seen much usages of this kind of getters that allow changing the internals. However, it does allow you to write a single method for reading and writing the value of the member.
In my opinion, I would call it a code smell as it makes it harder to understand which callers do actual modifications.
The story is off course different when returning a const reference to a member, as that might prevent copies. Though preventing the copy of a pointer doesn't add value.
Most of the C++11 code that takes std::initializer_list I've seen takes it by value, but sometimes it is taken by rvalue reference. Is there any good reason to do this?
For example, almost every example I've come across does this:
class A {
public:
A(std::initializer_list<int>);
};
But I keep seeing this done occasionally:
class B {
public:
B(std::initializer_list<int> &&);
};
I understand the use and purpose of rvalue references in general, but why would one of these be preferred over the other in the case of a std::initializer_list? The only thing I could think of is that class A allows the initializer list to be constructed separately, and class B prevents this.
std::initializer_list<int> values {1,2,3,4};
A a(values); // valid
B b(values); // error
But I can't think of a good reason why preventing that would be a desirable thing to accomplish.
So, why would one take a std::initializer_list by rvalue reference instead of by value?
I'm not sure I have a good reason, but my guess would be that the author of the code may have thought that passing an initializer list by value would make unnecessary copies of the elements in the list. This is, of course, not true - copying an initializer list does not copy the underlying values.
std::initializer_list embodies reference semantics even when passed by value, so passing by reference is at best misleading. (It only contains non-owning pointers.)
There are universal references which bind to anything, but they cannot be initialized by the braced-init-list syntax (i.e. { x, y }), so getting an initializer_list reference that way would take a combination of circumstances.
I have a class which accumulates information about a set of objects, and can act as either a functor or an output iterator. This allows me to do things like:
std::vector<Foo> v;
Foo const x = std::for_each(v.begin(), v.end(), Joiner<Foo>());
and
Foo const x = std::copy(v.begin(), v.end(), Joiner<Foo>());
Now, in theory, the compiler should be able to use the copy elision and return-value optimizations so that only a single Joiner object needs to be created. In practice, however, the function makes a copy on which to operate and then copies that back to the result, even in fully-optimized builds.
If I create the functor as an lvalue, the compiler creates two extra copies instead of one:
Joiner<Foo> joiner;
Foo const x = std::copy(v.begin(), v.end(), joiner);
If I awkwardly force the template type to a reference it passes in a reference, but then makes a copy of it anyway and returns a dangling reference to the (now-destroyed) temporary copy:
x = std::copy<Container::const_iterator, Joiner<Foo>&>(...));
I can make the copies cheap by using a reference to the state rather than the state itself in the functor in the style of std::inserter, leading to something like this:
Foo output;
std::copy(v.begin(), v.end(), Joiner<Foo>(output));
But this makes it impossible to use the "functional" style of immutable objects, and just generally isn't as nice.
Is there some way to encourage the compiler to elide the temporary copies, or make it pass a reference all the way through and return that same reference?
You have stumbled upon an often complained about behavior with <algorithm>. There are no restrictions on what they can do with the functor, so the answer to your question is no: there is no way to encourage the compiler to elide the copies. It's not (always) the compiler, it's the library implementation. They just like to pass around functors by value (think of std::sort doing a qsort, passing in the functor by value to recursive calls, etc).
You have also stumbled upon the exact solution everyone uses: have a functor keep a reference to the state, so all copies refer to the same state when this is desired.
I found this ironic:
But this makes it impossible to use the "functional" style of immutable objects, and just generally isn't as nice.
...since this whole question is predicated on you having a complicated stateful functor, where creating copies is problematic. If you were using "functional" style immutable objects this would be a non-issue - the extra copies wouldn't be a problem, would they?
If you have a recent compiler (At least Visual Studio 2008 SP1 or GCC 4.4 I think) you can use std::ref/std::cref
#include <string>
#include <vector>
#include <functional> // for std::cref
#include <algorithm>
#include <iostream>
template <typename T>
class SuperHeavyFunctor
{
std::vector<char> v500mo;
//ban copy
SuperHeavyFunctor(const SuperHeavyFunctor&);
SuperHeavyFunctor& operator=(const SuperHeavyFunctor&);
public:
SuperHeavyFunctor():v500mo(500*1024*1024){}
void operator()(const T& t) const { std::cout << t << std::endl; }
};
int main()
{
std::vector<std::string> v; v.push_back("Hello"); v.push_back("world");
std::for_each(v.begin(), v.end(), std::cref(SuperHeavyFunctor<std::string>()));
return 0;
}
Edit : Actually, the MSVC10's implementation of reference_wrapper don't seem to known how to deduce the return type of function object operator(). I had to derive SuperHeavyFunctor from std::unary_function<T, void> to make it work.
Just a quick note, for_each, accumulate, transform (2nd form), provide no order guarantee when traversing the provided range.
This makes sense for implementers to provide mulit-threaded/concurrent versions of these functions.
Hence it is reasonable that the algorithm be able to provide an equivalent instance (a new copy) of the functor passed in.
Be wary when making stateful functors.
RVO is just that -- return value optimization. Most compilers, today, have this turned-on by default. However, argument passing is not returning a value. You possibly cannot expect one optimization to fit in everywhere.
Refer to conditions for copy elision is defined clearly in 12.8, para 15, item 3.
when a temporary class object that has
not been bound to a reference (12.2)
would be copied to a class object with
the same cv-unqualified type, the copy
operation can be omitted by
constructing the temporary object
directly into the target of the
omitted copy
[emphasis mine]
The LHS Foo is const qualified, the temporary is not. IMHO, this precludes the possibility of copy-elision.
For a solution that will work with pre-c++11 code, you may consider using boost::function along with boost::ref(as boost::reference_wrapper alone doesn't has an overloaded operator(), unlike std::reference_wrapper which indeed does). From this page http://www.boost.org/doc/libs/1_55_0/doc/html/function/tutorial.html#idp95780904, you can double wrap your functor inside a boost::ref then a boost::function object. I tried that solution and it worked flawlessly.
For c++11, you can just go with std::ref and it'll do the job.