0

我正在尝试编写表达式模板,但遇到了一个我不知道如何解决的问题。我读过 C++ Templates: The Complete Guide 但他们似乎没有解决这个问题。

作为一个例子,考虑一个集合类型set(整数)的表达式模板,它具有标准集合操作交集、联合、否定、异或、差异等。这些函数在迭代器方面都有有效的实现,所以我想要我的表达式模板类具有类似迭代器的接口。例如,

class set_expr_set
{
  set::iter i;

  set_expr_set (const set &s) : i(s) { }

  operator bool () const { return (bool)i; }
  void operator ++ () { i ++; }
  int val () { return *i; }  
}

然后我有表达式模板类set_expr_union等。现在,问题是,与表达式模板表达式相对应创建的对象都是临时的,因此是常量,但是要评估表达式我需要遍历值(调用++val),而这些是非常量的。我不能声明set::operator = (set_expr &)为非常量,因为临时对象不会绑定非常量参数。我可以抛弃 const-ness operator =,但这感觉不是正确的解决方案。

我的例子没有足够的细节来说明问题,我很乐意澄清。

编辑:这里有更多细节。假设set_expr_union也有上面的set_expr_intersection接口:operator ++和。另外,假设我有valoperator bool

template<class T>
class set_expr
{
  T t;
  ...;
}

其中 T 旨在成为set_expr_union等之一,并且set_expr还导出t++, val, bool接口。

表达式模板对象通过各种运算符产生,例如:

template<class T1, class T2>
set_expr<set_expr_intersection>
operator & (const set_expr<T1> &e1, const set_expr<T2> &e2)
{
  return set_expr<set_expr_intersection> (set_expr_intersection (e1.t, e2.t));
}

确实,与运算符返回值对应的临时值是问题所在。

现在,考虑

class set
{
  ...;

  template<class T>
  set &operator = (const set_expr<T> &e)
  {
    clear ();
    for (; e; e ++)
      add_element (e.val ());
  }
};

我想在类似的东西中使用它set3 = set1 & set2

这是我想写的那种代码。

4

1 回答 1

1

一种解决方案是使您的集合表达式复制可构造和可分配(如果它们相对轻量级,这应该不是一个大问题,这似乎是这种情况)。在集合赋值运算符中,您创建集合表达式的副本并迭代该副本。

template<class T>
set& operator=(const set_expr<T> &e) {
  clear ();
  for (set_expr<T> i = e; i; i++) {
    add_element (i.val());
  }
  return *this;
}

如果复制集合表达式的成本太高,请考虑迁移到 c++11 并阅读移动语义。

于 2011-12-30T13:10:46.820 回答