没有取消引用/解包对象的标准方法?

No standard way to dereference/unwrap objects?

本文关键字:对象 标准 方法 取消 引用 包对象      更新时间:2023-10-16

在编写通用代码时,我经常发现自己处于这样的情况:我的 lib 用户提供的数据类型T可能需要直接是某种具体类型,但同时又是指向类型。当 lib 中的泛型操作用于指向类型而不是指针时,这表示一个问题。有没有取消引用的标准方法?例如,像这样:

namespace std
{
template <typename T>
T& deref( T& t ){ return t; }
template <typename T>
T& deref( T* t ){ return *t; }
template <typename T>
T& deref( std::unique_ptr<T>& t ){ return *t; }
template <typename T>
T& deref( std::shared_ptr<T>& t ){ return *t; }
template <typename T>
T& deref( std::reference_wrapper<T>& t ){ return t.get(); }
}

这样我的代码将以用户决定的原始形式存储T,但会对std::deref( t )执行操作(例如operator==operator<<(

据我所知,没有任何这样的功能。受这个答案的启发,自己写并不算太重(好吧,你自己已经做了,这个变体将扩展到任何提供operator*的东西,不过(:

// first starting with some helper functions:
// return references as references!
template <typename T>
decltype(auto) doDeref(T& t, ...)
{
return t;
}
// if some custom operator* returns a temporary, we cannot bind to normal
// reference, so we'll accept as rvalue reference instead:
template <typename T>
decltype(auto) doDeref(T&& t, ...)
{
return std::move(t);
}
// specifically: anything that can be dereferenced:
template <typename T>
decltype(auto) doDeref(T& t, std::remove_reference<decltype(*t)>*)
//                                ^ to avoid trying to form pointer to reference
{
return doDeref(*t, nullptr);
}
// a temporary that might be dereferencable:
template <typename T>
decltype(auto) doDeref(T&& t, std::remove_reference<decltype(*t)>*)
{
return doDeref(*t, nullptr);
}
// reference wrapper; accept as const (!)
// be aware that return type still is non-const unless underlying
// type (i. e. T) is already const as well!
decltype(auto) doDeref(std::reference_wrapper<T> const& t)
{
return doDeref(t.get(), nullptr);
}
// and finally: the main functions calling the helpers:
template <typename T>
decltype(auto) deref(T& t)
{
return doDeref(t, nullptr);
}
// again to allow temporaries...
template <typename T>
decltype(auto) deref(T&& t)
{
return doDeref(std::move(t), nullptr);
}

奖励:对于不适合正常取消引用模式(如std::reference_wrapper(的其他类型,这甚至是可扩展的,只需提供调用适当 getter 的另一个重载(如果类同时提供 const 和非 const getter,您可能需要为非 const 和 const 普通引用以及 rvalue 引用提供所有重载(。