Reputation: 1543
Let's say, I have an std::any
that store type T in it. Is it possible to create another std::any
that will contain type std::reference_wrapper<const T>
? Like
std::any original = std::string("Test string");
std::any reference;
// Magic here
auto ref = std::any_cast<std::reference_wrapper<const std::string>>(reference); // Works
Upvotes: 1
Views: 854
Reputation: 14724
If you want this badly enough, you can create a little wrapper class around a std::any
that captures and type-erases the "convert to reference_wrapper
" operation when it is constructed:
class any_refable
{
public:
std::any ref() const { return converter(any); }
const std::any& get() const& { return any; }
const std::any&& get() const&& { return std::move(any); }
std::any& get() & { return any; }
std::any&& get() && { return std::move(any); }
any_refable() = default;
template <typename T, typename = std::enable_if_t<! std::is_same_v<std::decay_t<T>, any_refable>>>
any_refable(T&& v) : any(std::forward<T>(v)), converter(make_converter<std::decay_t<T>>()) {}
template <typename T, typename = std::enable_if_t<! std::is_same_v<std::decay_t<T>, any_refable>>>
any_refable& operator=(T&& v) { any = std::forward<T>(v); converter = make_converter<std::decay_t<T>>(); return *this; }
private:
using converter_t = std::any (*)(const std::any&);
std::any any;
converter_t converter = nullptr;
template <typename T>
static converter_t make_converter() {
return [](const std::any& any) { return std::any(std::cref(std::any_cast<const T&>(any))); };
}
};
Upvotes: 1
Reputation: 5095
The following works:
#include <iostream>
#include <any>
#include <functional>
int main() {
std::any original = std::string("Test string");
std::any ref = std::cref(std::any_cast<const std::string&>(original));
std::any_cast<std::string&>(original)[0] = 'X';
std::cout << std::any_cast<std::reference_wrapper<const std::string>>(ref).get() << '\n'; // Prints Xest string
}
Edit: As said in the comment, this only works if the type is known at compile time. If the type of the contained object is arbitrary, it is impossible, since the std::reference_wrapper
has to be constructed at some point and for this it needs to know the type it has to wrap at compile time, there is no way around this since C++ is statically typed.
Upvotes: 0
Reputation: 96896
It is impossible, unless you know the exact stored type (see the other answer), or the list of possible types (in which case you can switch
over original.type()
).
Upvotes: 1