编写值包装器类的最佳方法 [英] Best way to write a value wrapper class

查看:68
本文介绍了编写值包装器类的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我需要编写一个充当值包装器的类:

Supose I need to write a class which acts as a wrapper for values:

template<typename T>
struct value_wrapper
{
    T value;

    value_wrapper( const T& v ) : value( v ) {}

    //etc...
};

该类被设计为用作原始值的别名,因此,如果该值是rvalue,包装器保存值,如果是左值,则包装器保存对它的引用。
该类应该重载,例如比较运算符,并以这种方式使用:

The class is dessigned to be used as an alias of the original value, so if that value was an rvalue, the wrapper holds the value, and if it was an lvalue the wrapper holds a reference to it. The class is supposed to overload, say, comparison operators and be used in this way:

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

我的问题是:什么是最佳(有效)实施方式
这个问题似乎很广泛,我的意思是:

My question is: Whats the best (efficient) way to implement such thing? That questions seems to broad, I mean:


  • 我如何定义成员 value?是否像 T& 表示左值, T 表示右值? / li>
  • 是否有任何标准方法可以编写这种通用(rvalue和lvalue)别名?

  • How I define the member value? As T& for lvalues, and T for rvalues?
  • Is there any standard way to write this kind of universal (rvalue and lvalue) alias?

推荐答案

我认为Kerrek SB通过提供专业化服务走上了正确的路(

I think Kerrek SB is on the right track by providing a specialization (got my +1 a long time ago), so each case is handled most efficiently.

问题是您不能只添加隐式转换运算符,并且如果您想提供自己的转换符,那么问题就解决了。

The problem is you can't just add implicit conversion operators and if you want to provide your own operator overloads, things can become quite tricky.

我想出的解决方案试图通过将信息(某些情况下将某个变量放入布尔型模板参数中)来解决此问题。 。以下是 value_wrapper 类的基本框架:

The solution I came up with tries to deal with this by putting the information which case a certain variable is into a boolean template parameter. Here's the basic framework for the value_wrapper class:

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

棘手的部分是包装值的便捷方法:

The tricky part is the convenience method to wrap the values:

// 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 的第一个模板参数始终是衰减类型,现在使一切变得更容易:

That way value_wrapper's first template parameter is always the decayed type, which makes everything easier now:

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()以统一的方式)

(obviously you want to implement them differently, but you can always access the stored values via cref() in a uniform way)

实时示例

如果您需要非恒定访问,等等。但是我希望以上内容能帮助您入门。如果您需要更多帮助/想法,请随时询问:)

You might need to adjust this if you need non-constant access, etc. but I hope the above gets you started. If you need more help/ideas, feel free to ask :)

这篇关于编写值包装器类的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆