标签: expression-templates

表达式模板和C++ 11

让我们看一下表达式模板的一个特殊优点:ET可用于避免在重载运算符中出现的内存中的矢量大小临时值,如:

template<typename T>
std::vector<T> operator+(const std::vector<T>& a, const std::vector<T>& b)
{
  std::vector<T> tmp;   // vector-sized temporary
  for_each(...);
  return tmp;
}
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,此函数的return语句应用移动语义.没有矢量的副本.这是一场胜利.

但是,如果我看一个像这样的简单表达式

d = a + b + c;
Run Code Online (Sandbox Code Playgroud)

我看到上面的函数被调用两次(两者都有operator+),而最后的赋值可以用移动语义来完成.

总共执行2个循环.意思是我把一个临时的,然后读回来.对于大向量,这不属于缓存.这比表达模板更糟糕.他们可以在一个循环中完成整个过程.ET可以执行上述代码,相当于:

for(int i=0 ; i < vec_length ; ++i)
  d[i] = a[i] + b[i] + c[i];
Run Code Online (Sandbox Code Playgroud)

我想知道lambdas与移动语义或任何其他新功能一起是否可以像ET一样好.有什么想法吗?

编辑:

基本上,使用ET技术,编译器构建一个解析树,类似于代数表达式和它的类型系统.该树由内部节点和叶子节点组成.内部节点表示操作(加法,乘法等),叶节点表示对数据对象的引用.

我尝试以堆栈计算机的方式考虑整个计算过程:从操作堆栈中获取操作并从参数堆栈中提取下一个参数并评估操作.将结果放回堆栈等待操作.

为了表示这两个不同的对象(操作堆栈和数据叶堆栈),我将一个捆绑在一起std::tuple用于操作,一个 捆绑在一起std::tuple用于数据std::pair<>.最初我使用了a std:vector但导致了运行时开销.

整个过程分为两个阶段:堆栈机器初始化,其中初始化操作和参数堆栈.以及通过将配对的容器分配给向量来触发的评估阶段.

我创建了一个Vec包含私有array<int,5>(有效负载)的类,它具有一个带有"表达式"的重载赋值运算符.

operator*对于所有拍摄Vec和"表达"的组合,全局都会超负荷, 以便在我们不仅仅是的情况下也能正确处理a*b.(注意,我将这个教育示例转换为乘法 - 基本上是为了快速发现imull汇编程序.) …

c++ expression-templates c++11

34
推荐指数
2
解决办法
1万
查看次数

使用表达式模板时,根据lvalue/rvalue提供类的不同实现

问题

假设我们实现了一个string表示字符串的类.然后我们想要添加一个operator+连接两个strings的,并决定通过表达式模板实现它,以避免在执行时进行多次分配str1 + str2 + ... + strN.

运算符将如下所示:

stringbuilder<string, string> operator+(const string &a, const string &b)
Run Code Online (Sandbox Code Playgroud)

stringbuilder是一个模板类,它反过来重载operator+并具有隐式string转换运算符.几乎是标准的教科书练习:

template<class T, class U> class stringbuilder;

template<> class stringbuilder<string, string> {
    stringbuilder(const string &a, const string &b) : a(a), b(b) {};
    const string &a;
    const string &b;
    operator string() const;
    // ...
}

// recursive case similar,
// building a stringbuilder<stringbuilder<...>, string>
Run Code Online (Sandbox Code Playgroud)

只要有人这样做,上述实现就完美无缺

string result = str1 …
Run Code Online (Sandbox Code Playgroud)

c++ expression-templates auto c++11

20
推荐指数
1
解决办法
734
查看次数

如何集成使用表达式模板的库?

我想在我的程序中使用Eigen矩阵库作为线性代数引擎.Eigen使用表达式模板来实现延迟评估并简化循环和计算.

例如:

#include<Eigen/Core>

int main()
{
  int size = 40;
  // VectorXf is a vector of floats, with dynamic size.
  Eigen::VectorXf u(size), v(size), w(size), z(size);
  u = 2*v + w + 0.2*z;
}
Run Code Online (Sandbox Code Playgroud)

由于Eigen使用表达式模板,代码如

u = 2*v + w + 0.2*z;
Run Code Online (Sandbox Code Playgroud)

在上面提到的样品中,减少到长度为10的单个环(不是40,浮子被4个块放入调节器中)而不会产生临时的.多么酷啊?

但如果我像这样集成库:

class UsingEigen
{
    public:  
        UsingEigen(const Eigen::VectorXf& data):
            data_(data)
        {}

        UsingEigen operator + (const UsingEigen& adee)const
        {
            return UsingEigen(data_ + adee.data_);
        }

        ...
    private:
        Eigen::VectorXf data_;
}
Run Code Online (Sandbox Code Playgroud)

那么表达式就像:

UsingEigen a, b, c, d;
a = b + c …
Run Code Online (Sandbox Code Playgroud)

c++ templates encapsulation expression-templates eigen

17
推荐指数
1
解决办法
1178
查看次数

表达式模板没有完全内联

我已经完成了第一个数学库版本,下一步我想转向表达式模板来提高代码的性能.但是,我的初步结果与我的预期不同.我正在MSVC 2010中编译,在vanilla Release模式下(并且可以使用C++ 0x).

对于我将向您展示的大量代码提前道歉,在让人们看到我正在做的事情的同时,我尽可能地做到这一点.分析框架:

#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <limits>
#include <type_traits>
#include <vector>

namespace math
{
    class vector; // to be determined

    std::ostream& operator<<(std::ostream& stream, const vector& vec)
    {
        for (std::size_t i = 0; i < 4; ++i)
            stream << vec[i] << " ";

        return stream;
    }
}

// test framework
typedef std::vector<math::vector> array_type[3];
typedef std::vector<math::vector> vector_type;

float generate_float()
{
    return static_cast<float>(rand());
}

math::vector generate_vector()
{
    return math::vector(generate_float(), generate_float(),
                        generate_float(), generate_float());
} …
Run Code Online (Sandbox Code Playgroud)

c++ optimization inlining expression-templates

14
推荐指数
1
解决办法
544
查看次数

为什么“重载解决方案”偏向于不受约束的模板功能而不是更具体的模板功能?

我有一个带有乘法的最小表达模板库,即

template <typename T, typename U>
struct mul {
    const T &v1;
    const U &v2;
};

template <typename T, typename U>
mul<T, U> operator*(const T &one, const U &two) {
    std::cout << " called: mul<T, U> operator*(const T &one, const T &two)\n";
    return mul<T, U>{one, two};
}
Run Code Online (Sandbox Code Playgroud)

并转置,即

template <typename T>
struct transpose {
    const T &t;
};

template <typename T>
transpose<T> tran(const T &one) {
    return transpose<T>{one};
}
Run Code Online (Sandbox Code Playgroud)

我将介绍一些type AB,其中后者是前者的子类:

template <typename T>
struct A { …
Run Code Online (Sandbox Code Playgroud)

c++ generic-programming sfinae expression-templates

14
推荐指数
1
解决办法
183
查看次数

表达式模板与手写代码

我目前正在编写一个C++模板表达式库,并将一些实例与程序集级别的手写代码进行比较.手写功能如下:

spinor multiply(vector const& a, vector const& b)
{
        spinor result = {
                a.at<1>() * b.at<1>() - a.at<2>() * b.at<2>()
                          - a.at<4>() * b.at<4>() - a.at<8>() * b.at<8>(),
                a.at<1>() * b.at<2>() - a.at<2>() * b.at<1>(),
                a.at<1>() * b.at<4>() - a.at<4>() * b.at<1>(),
                a.at<1>() * b.at<8>() - a.at<8>() * b.at<1>(),
                a.at<2>() * b.at<4>() - a.at<4>() * b.at<2>(),
                a.at<2>() * b.at<8>() - a.at<8>() * b.at<2>(),
                a.at<4>() * b.at<8>() - a.at<8>() * b.at<4>()
        };

        return result;
}
Run Code Online (Sandbox Code Playgroud)

vector类只是在四个双打的包装,其可以通过使用读出at<index>()的成员函数.由于设计决策,四个组件的索引1, …

c++ assembly gcc expression-templates c++11

11
推荐指数
1
解决办法
714
查看次数

使用比较运算符时检查多个值

我总是认为对于任何比较声明,即X == Y或者X != Y是格式,并且您将语句与&&或一起链接||.

有没有办法写X == (Y || Z)而不是X == Y || X == Z

编辑:既然已经确定这不可能干净利落,那怎么办呢?

c++ operator-overloading logical-operators expression-templates

11
推荐指数
1
解决办法
4896
查看次数

C++表达式模板的教程和介绍

有什么好的介绍来创建C++表达式模板系统?我想表达对用户定义类型的算法,同时避免临时值(可能很大),并学习如何直接执行此操作而不是应用现有库.

我找到了Todd Veldhuizen的原始论文Josuttis C++模板书中的一个例子,以及Kreft&Langer的一篇文章.在现代C++课程的第6讲中提到了Josuttis.POOMA库背景很好地介绍了表达模板.

我正在寻找简单明了的论述.

c++ arrays templates metaprogramming expression-templates

10
推荐指数
2
解决办法
5671
查看次数

将Boost.Proto语法与类型匹配

我正在尝试在Boost.Proto中创建一个匹配矢量类型的语法,但是当我给它一个该类型的终端时,它与语法不匹配.类型定义如下所示:

template <typename T, unsigned D>
struct vector
{
    typedef T scalar;
    enum { size = D };

    scalar& operator[](unsigned i)
    {
        return m_components[i];
    }

    scalar const& operator[](unsigned i) const
    {
        return m_components[i];
    }

private:
    scalar m_components[size];
};
Run Code Online (Sandbox Code Playgroud)

我试图匹配的语法看起来像这样:

namespace proto = boost::proto;
using proto::_;
using proto::N;

struct test:
    proto::terminal<vector<_, N> >
{};
Run Code Online (Sandbox Code Playgroud)

比赛失败:

int main ()
{
    BOOST_MPL_ASSERT((proto::matches<proto::terminal<vector<float, 2> >::type, test>));
}
Run Code Online (Sandbox Code Playgroud)

如何制作与特定类型匹配的语法?

编辑:

似乎proto :: _和proto :: N在自定义类型中不用作通配符.代码用这个语法编译(matches断言传递):

struct test:
    proto::terminal<vector<float, 2> >
{};
Run Code Online (Sandbox Code Playgroud)

但是当其中任何一个通配符属于该类型时,它都不起作用:

struct …
Run Code Online (Sandbox Code Playgroud)

c++ boost expression-templates boost-proto

10
推荐指数
2
解决办法
752
查看次数

表达式模板和范围基于C++ 11

据我所知,表达式模板将在C++ 11中基于范围而中断,因为for (auto x : expr)它具有隐含性auto&& __range = expr,这将导致悬空引用.

有没有办法创建表达式模板类,以便它们能够正确地使用基于范围的行为,或者至少抛出编译错误?

基本上,我想防止表达式模板正确编译但由于悬空引用而在运行时失败的可能性.我不介意在基于for的范围内使用表达式模板之前必须将表达式模板包装起来,只要在用户忘记包装表达式模板时没有静默运行时错误.

c++ expression-templates c++11

9
推荐指数
2
解决办法
543
查看次数