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

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

问题描述

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

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 ...

其中 ... 表示进一步的语法(对这个问题无用).但是,如果我尝试对其进行编译,则无论我使用哪种预处理程序翻译将采用"为运算符"(以逗号分隔,因为从技术上讲,它都不是运算符,但是转换阶段会将其转换为一个类,例如,运算符*可用),编译器仍会尝试评估/计算x * x的来源(并且,由于先前未声明x * x,因为它在'in'阶段被进一步声明),相反)找不到它并抛出编译错误.

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.

我当前的想法实质上是尝试将表达式放置在lambda内(由于我们可以推断出容器的类型,因此我们可以使用正确的类型声明 x ,例如[](decltype(* begin(container))x){return x * x} -因此,当编译器查看此语句时,它是有效的,并且不会引发任何错误),但是,我正在运行实际实现此目标的错误.

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.

因此,我的问题是:有没有一种方法/冻结"我表达的 x * x 部分的最佳方法是什么?

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

编辑:为了澄清我的问题,请采取以下措施.假设以合理的方式定义了operator-,以便以下尝试实现上述 take ... 语法的作用:

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()-容器...

编译此语句时,编译器将引发错误;没有声明x,所以x * x没有意义(x也没有-MyInClass()等).我要实现的目标是找到一种方法,使用任何可用的伏都教魔术来编译上面的表达式,而无需知道x的类型(或者实际上,它将被命名为x;它可以预先命名为"somestupidvariablename").

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.

推荐答案

我给出的答案与之前的答案非常相似,但是使用的是 actual 表达式模板,该模板应该快得多.不幸的是,MSVC10在尝试编译时会崩溃,但是MSVC11,GCC 4.7.0和Clang 3.2都可以编译并正常运行.(所有其他版本未经测试)

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

您可以看到,它的用法与我之前的代码完全相同,只是现在所有函数都是在编译时决定的,这意味着它的速度与lambda完全相同.实际上,C ++ 11 lambdas先于 boost:: lambda 适用于很多类似概念.

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.

这是一个单独的答案,因为代码 far 不同,而 far 更复杂/更令人生畏.这就是为什么实现本身不在答案中的原因.

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.

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

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