编写值包装类的最佳方式
Best way to write a value wrapper class
Supose我需要编写一个类,作为值的包装器:
template<typename T>
struct value_wrapper
{
T value;
value_wrapper( const T& v ) : value( v ) {}
//etc...
};
该类被设计为用作原始值的别名,因此,如果该值是右值,则包装器将保存该值,如果它是左值,则封装器将保存对它的引用。该类应该重载比较运算符,并以这种方式使用:
template<typename T , typename U>
bool f( const T& lhs , const T& rhs )
{
return wrapper( lhs ) == wrapper( rhs );
}
或者这个:
int main()
{
int a , b;
bool flag = wrapper( a ) == wrapper( b ) || wrapper( a ) == wrapper( 2 );
}
我的问题是:实现这种事情的最佳(有效)方式是什么这个问题似乎很宽泛,我的意思是:
- 如何将成员
value?
定义为左值的T&
,以及右值的T
- 有没有标准的方法来编写这种通用(右值和左值)别名
我只需提供合适的转换运算符:
#include <utility>
#include <type_traits>
template <typename T> struct Wrapper
{
static_assert(!std::is_reference<T>::value, "Do not use a reference type");
using type = T;
T value;
Wrapper(T && t) : value(std::move(t)) {}
Wrapper(T const & t) : value(t) {}
operator T const & () const noexcept { return value; }
operator T & () & noexcept { return value; }
operator T && () && noexcept { return std::move(value); }
// maybe some more CV variants...
};
template <typename U> struct Wrapper<U &>
{
using type = U &;
U & ref;
Wrapper(U & u) : ref(u) {}
operator U & () { return ref; }
};
我会附带一个推导函数:
template <typename T> Wrapper<T> wrap(T && t)
{ return Wrapper<T>(std::forward<T>(t)); }
示例用法:
int n = 10;
bool b = wrap(n) == wrap(5 + 5)
转换运算符允许您使用在基础类型上定义的任何运算符。
我认为Kerrek SB通过提供专业化(很久以前就获得了+1)走在了正确的轨道上,因此每个案例都得到了最有效的处理。
问题是,你不能只添加隐式转换运算符,如果你想提供自己的运算符重载,事情可能会变得相当棘手。
我提出的解决方案试图通过将某个变量的大小写信息放入布尔模板参数来处理这个问题。以下是value_wrapper
类的基本框架:
template< typename T, bool >
class value_wrapper
{
private:
T t_; // store a value
public:
explicit value_wrapper( T&& t ) : t_( std::move( t ) ) {}
const T& cref() const { return t_; }
};
template< typename T >
struct value_wrapper< T, true > // specialization for lvalue references
{
private:
const T& t_; // store a reference
public:
explicit value_wrapper( const T& t ) : t_( t ) {}
const T& cref() const { return t_; }
};
棘手的部分是包装值的方便方法:
// needs a better name and needs to be moved into a "detail" or "impl" namespace
template< typename T >
using helper = value_wrapper< typename std::decay< T >::type,
std::is_lvalue_reference< T >::value >;
template< typename T >
helper< T > wrap( T&& t )
{
return helper< T >( std::forward< T >( t ) );
}
这样一来,value_wrapper
的第一个模板参数总是衰减类型,这使得现在一切都变得更容易:
template< typename T, bool BL, bool BR >
bool operator==( const value_wrapper< T, BL >& lhs, const value_wrapper< T, BR >& rhs )
{
return lhs.cref() == rhs.cref();
}
(显然,您希望以不同的方式实现它们,但您始终可以通过cref()
以统一的方式访问存储的值)
实时示例
如果你需要非恒定访问等,你可能需要调整它,但我希望以上内容能让你开始。如果您需要更多帮助/想法,请随时询问:)
相关文章:
- 在c代码之间共享数据的最佳方式
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 在reactor中存储eventHandlers的最佳方式是什么
- 在AVX通道中混洗的最佳方式
- 从 T 创建 std::future 的最佳方式<T>
- C++:使用 std::unique_ptr 访问重载运算符++的最佳方式?
- 对列表列表中的元素进行分组的最佳方式
- 利用 GPU 的最佳方式
- 使用 QT C++过滤大数据的最佳方式
- 算法设计:用边界数字表示 2D 网格的最佳方式,以C++?
- 在C++中共享键值对的最佳方式
- 为Catch2中的外部文本文件指定路径的最佳方式
- 代表Quarto棋盘游戏棋子的最佳方式
- 等待线程的最佳方式是什么
- 将uint8_t*buffer和size_tbufferlen从C++传递到C中的API函数的最佳方式是什么
- 创建控制台菜单C++的最佳方式
- 只显示片段着色器的最佳方式是什么
- 复制文件的最佳方式是什么,以便我可以在复制过程中轻松取消复制?