'冻结'一个表达式 [英] 'Freezing' an expression

查看:115
本文介绍了'冻结'一个表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C ++表达式,我希望冻结。通过这个,我的意思是我有如下语法:

 在容器中使用x * x x b  

其中 ... 到这个问题)语法。但是,如果我试图编译这个,无论什么预处理器翻译我已经使用'取'一个'操作符'(在倒置逗号,因为它在技术上不是一个运算符,但翻译阶段变成一个类, ,运算符*可用),编译器仍然尝试评估/工作出x * x来自哪里(和,因为它没有被声明以前(因为它在'in'阶段进一步声明)



我现在的想法基本上包括将表达式放置在lambda中(因为我们可以推导出类型可以使用正确的类型声明 x ,例如 [](decltype(* begin(container))x){return x * x} - 因此,当编译器查看这个语句时,它是有效的,没有错误被抛出),但是,我遇到的错误实际上实现了这一点。



因此,我的问题是:
有什么方法/什么是'冻结' x * x


为了澄清我的问题,请采取以下措施。假设操作符是以一种正常的方式定义的,这样下面的尝试就可以实现上面的 ... 语法:



MyTakeClass() - x * x - MyWithClass() - x - MyInClass() - container ...


b $ b

编译此语句时,编译器将抛出一个错误; x未声明,所以x * x没有意义(也不是x - MyInClass()等等)。我想实现的是找到一种方法来使上述表达式编译,使用任何巫术魔法可用,没有知道x的类型(或实际上,它将被命名为x ;它可以被预先命名为somestupidvariablename)。

解决方案

我提出了一个非常类似于我以前的答案,但使用实际应该快得多。不幸的是,MSVC10崩溃,当它试图编译这个,但MSVC11,GCC 4.7.0和Clang 3.2所有编译和运行它只是罚款。 (未经测试的所有其他版本)



这里是模板的用法。实施代码为此处

  #define take 
#define with,
#define in>> =

//容器的函数调用
template< class lhsexpr, class container>
lhsexpr operator>> =(lhsexpr lhs,container& rhs)
{
for(auto it = rhs.begin(); it!= rhs.end(); ++ it )
* it = lhs(* it);
return lhs;
}

int main(){
std :: vector< int> container0;
container0.push_back(-4);
container0.push_back(0);
container0.push_back(3);
获取x * x,x在container0中; // this is the magic line
for(auto it = container0.begin(); it!= container0.end(); ++ it)
std :: cout< * it< '';
std :: cout<< '\\\
';

auto a = x + x * x +'a'* x;
auto b = a; // make sure copies work
b in container0;
b in container1;
std :: cout<< sizeof(b);

return 0;
}

如你所见,这与我之前的代码完全一样, 所有函数都在编译时决定,这意味着它将具有与lambda完全相同的速度。事实上,C ++ 11 lambdas之前是由 boost :: lambda ,它可以处理非常类似的概念。



answer,因为代码 far 不同,并且 far 更复杂/令人恐惧。这也是为什么实现不在答案本身。


I have a C++ expression that I wish to 'freeze'. By this, I mean I have syntax like the following:

take x*x with x in container ...

where the ... indicates further (non-useful to this problem) syntax. However, if I attempt to compile this, no matter what preprocessor translations I've used to make 'take' an 'operator' (in inverted commas because it's technically not an operator, but the translation phase turns it into a class with, say, operator* available to it), the compiler still attempts to evaluate / work out where the x*x is coming from, (and, since it hasn't been declared previously (as it's declared further at the 'in' stage), it instead) can't find it and throws a compile error.

My current idea essentially involves attempting to place the expression inside a lambda (and since we can deduce the type of the container, we can declare x with the right type as, say, [](decltype(*begin(container)) x) { return x*x } -- thus, when the compiler looks at this statement, it's valid and no error is thrown), however, I'm running into errors actually achieving this.

Thus, my question is: Is there a way / what's the best way to 'freeze' the x*x part of my expression?

EDIT: In an attempt to clarify my question, take the following. Assume that the operator- is defined in a sane way so that the following attempts to achieve what the above take ... syntax does:

MyTakeClass() - x*x - MyWithClass() - x - MyInClass() - container ...

When this statement is compiled, the compiler will throw an error; x is not declared so x*x makes no sense (nor does x - MyInClass(), etc, etc). What I'm trying to achieve is to find a way to make the above expression compile, using any voodoo magic available, without knowing the type of x (or, in fact, that it will be named x; it could viably be named 'somestupidvariablename') in advance.

解决方案

I made an answer very similar to my previous answer, but using actual expression templates, which should be much faster. Unfortunately, MSVC10 crashes when it attempts to compile this, but MSVC11, GCC 4.7.0 and Clang 3.2 all compile and run it just fine. (All other versions untested)

Here's the usage of the templates. Implementation code is here.

#define take 
#define with ,
#define in >>= 

//function call for containers 
template<class lhsexpr, class container>
lhsexpr operator>>=(lhsexpr lhs, container& rhs)
{
    for(auto it=rhs.begin(); it!=rhs.end(); ++it)
        *it = lhs(*it);
    return lhs;
}

int main() {
    std::vector<int> container0;
    container0.push_back(-4);
    container0.push_back(0);
    container0.push_back(3);
    take x*x with x in container0; //here's the magic line
    for(auto it=container0.begin(); it!=container0.end(); ++it)
        std::cout << *it << ' ';
    std::cout << '\n';

    auto a = x+x*x+'a'*x;
    auto b = a; //make sure copies work
    b in container0;
    b in container1;
    std::cout << sizeof(b);

    return 0;
}

As you can see, this is used exactly like my previous code, except now all the functions are decided at compile time, which means this will have exactly the same speed as a lambda. In fact, C++11 lambdas were preceeded by boost::lambda which works on very similar concepts.

This is a separate answer, because the code is far different, and far more complicated/intimidating. That's also why the implementation is not in the answer itself.

这篇关于'冻结'一个表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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