表达式模板中需要非常量表达式类
我正在尝试编写一个表达式模板,但遇到了一个不知道如何解决的问题。我读过《C++ 模板:完整指南》,但他们似乎没有解决这个问题。
作为一个例子,考虑一个集合类型 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
等。现在的问题是,与表达式模板 expression 相对应创建的对象都是临时对象,因此是 const,但要评估我需要的表达式迭代这些值(调用 ++
和 val
),这些值是非常量的。我无法将 set::operator = (set_expr &)
声明为非常量,因为临时变量不会绑定非常量参数。我可以放弃 operator =
中的 const-ness,但这感觉不是正确的解决方案。
我的例子没有足够的细节来阐明问题,我很乐意澄清。
编辑:这里有一些更多细节。假设 set_expr_union
和 set_expr_intersection
也具有上述接口:operator ++
、val
和 operator 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 & 之类的东西中使用它。设置2。
这就是我想要编写的代码。
I'm trying to write an expression template and I've run into a problem I don't know how to solve. I've read C++ Templates: The Complete Guide but they don't seem to address this question.
As an example, consider a expression template for a set type set
(of integers) with the standard set operations intersection, union, negation, xor, difference, etc. These functions all have efficient implementations in terms of iterators, so I want my expression template classes to have an iterator-like interface. For example,
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; }
}
and then I have expression template classes set_expr_union
, etc. Now, the problem is, the objects created corresponding to expression templates expression are all temporaries and therefore const, but to evaluate the expression I need to iterate through the values (calling ++
and val
), and these are non-const. I can't declare set::operator = (set_expr &)
as non-const, because the temporaries won't bind a non-const parameter. I could cast away the const-ness in operator =
, but that doesn't feel like the right solution.
I'm my example doesn't have enough details to make the problem clear, I'll be happy to clarify.
EDIT: Here are some more details. Suppose set_expr_union
and set_expr_intersection
have the above interface, too: operator ++
, val
and operator bool
. Also, suppose I have
template<class T>
class set_expr
{
T t;
...;
}
where T is intended to be one of set_expr_union
, etc. and set_expr
also exports t
's ++, val, bool
interface.
The expression template objects arise through various operators, e.g.:
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));
}
Really, the temporary corresponding to the return value from the operators is where the problem lies.
Now, consider
class set
{
...;
template<class T>
set &operator = (const set_expr<T> &e)
{
clear ();
for (; e; e ++)
add_element (e.val ());
}
};
which I want to use in something like set3 = set1 & set2
.
This is the kind of code I want to write.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一种解决方案是使集合表达式副本可构造和可分配(如果它们相对轻量级,这应该不是一个大问题,似乎就是这种情况)。在集合赋值运算符中,您创建集合表达式的副本并迭代该副本。
如果复制集合表达式的成本太高,请考虑转向 c++11 并阅读移动语义。
One solution is to make your set expressions copy constructable and assignable (which shouldn't be a big problem if they are relatively light-weight, which seems to be the case). In the set assignment operator, you create a copy of the set expression and iterate over the copy.
If copying the set expressions turns out to be too expensive, consider moving to c++11 and reading up on move semantics.