DiscriminatedPtr<Types...>
是一个模板类,它允许存储指向多个可能类型之一的对象的指针,或者它可以是空的。这种类型的指针被称为判别式指针,因为它能够区分并安全地访问它所指向的对象的类型。以下是对 DiscriminatedPtr
的详细解释:
类型安全
DiscriminatedPtr
是类型安全的。这意味着你只能获取到与你放入的类型相对应的指针。- 如果你尝试获取一个与你存储的类型不匹配的指针,
DiscriminatedPtr
会抛出一个异常(通常是一个std::invalid_argument
异常)。 - 另一个版本的获取方法(如
get_nothrow
)在类型不匹配时不会抛出异常,而是返回nullptr
。
非智能指针
DiscriminatedPtr
不是一个智能指针,它不会管理对象的生命周期。- 你需要负责释放(如果需要的话)任何用于存储指向对象的内存。
使用场景
DiscriminatedPtr
通常用于实现类型安全的联合(union)或变体(variant)类型,其中可以存储多种类型的值,但在任何给定时间只能存储其中一种类型。- 它允许在运行时安全地访问存储的值,同时避免在类型转换时出现错误。
使用示例:
struct Foo { };
struct Visitor {
std::string operator()(int* /* ptr */) { return "int"; }
std::string operator()(const int* /* ptr */) { return "const int"; }
std::string operator()(Foo* /* ptr */) { return "Foo"; }
std::string operator()(const Foo* /* ptr */) { return "const Foo"; }
};
typedef DiscriminatedPtr<int, Foo> Ptr;
Ptr p;
int a = 0;
p.set(&a);
EXPECT_EQ("int", p.apply(Visitor()));
EXPECT_EQ("const int", static_cast<const Ptr&>(p).apply(Visitor()));
Foo foo;
p.set(&foo);
EXPECT_EQ("Foo", p.apply(Visitor()));
EXPECT_EQ("const Foo", static_cast<const Ptr&>(p).apply(Visitor()));
EXPECT_EQ("Foo", apply_visitor(Visitor(), p));
EXPECT_EQ("const Foo", apply_visitor(Visitor(), static_cast<const Ptr&>(p)));
EXPECT_EQ("Foo", apply_visitor(Visitor(), std::move(p)));
p.clear();
EXPECT_THROW({p.apply(Visitor());}, std::invalid_argument);
DiscriminatedPtr的源码为:
template <typename... Types>
class DiscriminatedPtr {
static_assert(sizeof...(Types) < std::numeric_limits<uint16_t>::max(),
"too many types");
public:
DiscriminatedPtr() : data_