变量可能与一些辅助工具配合使用。
template<class X>
struct is_variant: std::false_type{};
template<class...Ts>
struct is_variant< std::variant<Ts...> >:std::true_type{};
template<class X>
constexpr bool is_variant_v = is_variant<X>{};
template<class F>
struct variant_method {
F f;
template<class Variant> requires (is_variant_v<std::decay_t<Variant>>)
friend auto operator->*( Variant && variant, variant_method const& self ) {
return [&](auto&&...args)->decltype(auto) {
return std::visit( [&](auto&& val)->decltype(auto) {
return self.f( decltype(val)(val), decltype(args)(args)... );
}, std::forward<Variant>(variant) );
};
}
};
template<class F>
variant_method(F&&)->variant_method<std::decay_t<F>>;
现在我们可以这样做:
constexpr variant_method dereference{ [](auto&& x)->decltype(auto) { return *x; } };
template<class T>
constexpr variant_method operator_{ [](auto&& x)->T { return static_cast<T>(x); } };
constexpr auto to_bool = operator_<bool>;
现在开始!
struct something {
int x = 0;
};
std::variant<std::shared_ptr<something>, something*> some_ptr;
some_ptr = new something;
if ((some_ptr->*to_bool)())
(some_ptr->*dereference)().x = 7;
some_ptr = std::make_shared<something>();
if ((some_ptr->*to_bool)())
(some_ptr->*dereference)().x = 3;
实时示例。
现在,我们可以将其包装得更漂亮。
template<class...Ts>
struct variant_ptr:std::variant<Ts...> {
using base = std::variant<Ts...>;
using base::base;
auto& operator*() const { return (((base const&)*this)->*dereference)(); }
auto& operator*() { return (((base&)*this)->*dereference)(); }
auto* get() const { return std::addressof(**this); }
auto* get() { return std::addressof(**this); }
auto* operator->() const { return get(); }
auto* operator->() { return get(); }
explicit operator bool() const { return (((base const&)*this)->*to_bool)(); }
};
现在我们要做的是:
variant_ptr<Foo*, std::shared_ptr<Foo>>
我們希望一切都“只是工作”。
示例可在
此处查看。
當然,我们可以跳过上面的所有variant_method内容,只需在variant_ptr中实现std :: visit。
哦,
这里有一个版本,通过向variant_method :: operator-&gt; *教授与从variant类型派生的类型交互的知识来摆脱那些base&amp;强制转换。
template<class...Ts>
constexpr decltype(auto) get_variant_base(std::variant<Ts...> const& x) { return x; }
template<class...Ts>
constexpr decltype(auto) get_variant_base(std::variant<Ts...>& x) { return x; }
template<class...Ts>
constexpr decltype(auto) get_variant_base(std::variant<Ts...>&& x) { return std::move(x); }
constexpr auto get_variant_base_lambda = [](auto&&x)->decltype(get_variant_base(decltype(x)(x))){ return get_variant_base(decltype(x)(x)); };
template<class X>
constexpr bool is_variant_derived_v = std::is_invocable_v< decltype(get_variant_base_lambda), X >;
template<class F>
struct variant_method {
F f;
template<class Variant> requires (is_variant_derived_v<Variant>)
friend auto operator->*( Variant && variant, variant_method const& self ) {
return [&](auto&&...args)->decltype(auto) {
return std::visit( [&](auto&& val)->decltype(auto) {
return self.f( decltype(val)(val), decltype(args)(args)... );
}, get_variant_base(std::forward<Variant>(variant)) );
};
}
};
template<class...Ts>
struct variant_ptr:std::variant<Ts...> {
using base = std::variant<Ts...>;
using base::base;
auto& operator*() const { return ((*this)->*dereference)(); }
auto& operator*() { return ((*this)->*dereference)(); }
auto* get() const { return std::addressof(**this); }
auto* get() { return std::addressof(**this); }
auto* operator->() const { return get(); }
auto* operator->() { return get(); }
explicit operator bool() const { return ((*this)->*to_bool)(); }
};
Bar
添加一个构造函数,该构造函数接受一个std::shared_ptr<Foo>
? - NathanOliverBar
的所有权语义将是什么?原始指针没有明确的所有权语义,而shared_ptr
表示共享所有权(并通过其基础自动引用计数实现自动生命周期管理)。 - dfribBar
对象存储了一个Foo*
(裸指针),它是否拥有它(可能)指向的资源?或者Bar
只是它的观察者,依赖于其他人来处理该资源(但在Bar
使用完之前不会删除它)? - dfrib