重载大于操作符的操作符将用户定义类型强制转换为原语,信息丢失



在存在用户定义类型的c++库中,该类型将变量的符号值的文本表示添加到原始数据类型int, double,…bool:

template<typename T>
class Var {
    T value;
    //a datastructure containing Expressions and string representations of operators
    Expression expr; 
}

覆盖addition (+)的操作符:

#define OVERLOAD_ARITHMETIC_OPERATOR(op, opName) 
template<typename X, typename Y>
auto operator op(const X x, const Y y) ->
se::Var<decltype(__filter(x).getValue() op __filter(y).getValue())> 
{
    const auto __x = __filter(x);
    const auto __y = __filter(y);
    auto result = se::constructVar(__x.getValue() op __y.getValue());
    if(__x.isSymbolic() || __y.isSymbolic()) {
        result.setExpression(BINARY_EXPRESSION(opName, __x.getExpression(), __y.getExpression()));
    }
    return result;
}
OVERLOAD_ARITHMETIC_OPERATOR(+, ADD)

下面的程序:

main.cpp:

#define double Double
#define int Int
#define float Float
#define bool Bool
#include "aprogram.c"
#undef double 
#undef int
#undef float
#undef bool
int main(){
     std::cout << afunction();
}

aprogram.c:

int afunction(){
    double t1 = ... ;
    double t2 = ... ;
    return t1 + t2;
}

返回t1.expr + t2.expr

当重载操作符greater (>)时:

#define OVERLOAD_COND_OPERATOR(op, opName) 
template<typename X, typename Y>
se::Var<bool> operator op(const X x, const Y y)
{
    const auto __x = __filter(x);
    const auto __y = __filter(y);
    auto result = se::constructVar(__x.getValue() op __y.getValue());
    if(__x.isSymbolic() || __y.isSymbolic()) 
        result.setExpression(BINARY_EXPRESSION(opName, __x.getExpression(), __y.getExpression()));
    return result;
}
OVERLOAD_COND_OPERATOR(>, GREATER)

并将函数()中的返回值更改为return t1 > t2,我们期望得到类似的结果,t1.expr > t2.expr,但结果被强制转换为bool类型,并且存储在Var.expr中的信息丢失。

虽然我相信+>的操作符写得相似,你能帮我理解为什么>的行为不同吗?你能帮我找到通缉的行为吗?

请反馈我的问题:帮我帮你帮我。

发布后添加的信息

1/__filter()是一个返回数据结构Var的方法。在我的例子中Var被大大简化了,filter只返回包含T valueExpression expr的对象。

2/

typedef se::Var<double> Double;
typedef se::Var<int> Int;
typedef se::Var<char> Char;
typedef se::Var<float> Float;
typedef se::Var<bool> Bool;

你的程序将会做很多意想不到的事情,因为它有未定义的行为。

这是不允许的:

#define double Double
#define int Int
#define float Float
#define bool Bool

宏名必须是标识符,这些是关键字,而不是标识符。

第17.6.4.3节讲得很清楚:

翻译单元的#define#undef名称在词法上不能与关键字、表3中列出的标识符或7.6中描述的属性令牌相同。

如果程序在保留名称的上下文中声明或定义了该名称,则该程序的行为是未定义的。

最新更新