是否可以从 std::any 创建 std::any 与 std::reference_wrapper?

Is it possible to create std::any with std::reference_wrapper from just std::any?

本文关键字:std any reference wrapper 创建 是否      更新时间:2023-10-16

假设,我有一个存储类型T的std::any。是否可以创建另一个包含类型std::reference_wrapper<const T>std::any?喜欢

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

这是不可能的,除非您知道确切的存储类型(请参阅其他答案(或可能的类型列表(在这种情况下,您可以switchoriginal.type()(。

如果你非常想要这个,你可以围绕一个std::any创建一个小包装类,该包装类在构造"转换为reference_wrapper"操作时捕获并类型擦除:

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))); };
}
};

演示

以下作品:

#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
}

编辑:如注释中所述,这仅在编译时已知类型时才有效。如果包含对象的类型是任意的,则是不可能的,因为std::reference_wrapper必须在某个时候构造,为此它需要知道在编译时必须包装的类型,因此无法解决此问题,因为C++是静态类型的。