Неверные результаты с использованием auto с Eigen

Я получил разные результаты, используя auto, и используя Vector при суммировании двух векторов.

Мой код:

#include "stdafx.h"
#include <iostream>
#include "D:\externals\eigen_3_1_2\include\Eigen\Geometry"

typedef Eigen::Matrix<double, 3, 1>       Vector3;

void foo(const Vector3& Ha, volatile int j) 
{
    const auto resAuto = Ha + Vector3(0.,0.,j * 2.567);
    const Vector3 resVector3 = Ha + Vector3(0.,0.,j * 2.567);

    std::cout << "resAuto = " << resAuto <<std::endl;
    std::cout << "resVector3 = " << resVector3 <<std::endl;
}

int main(int argc, _TCHAR* argv[])
{
    Vector3 Ha(-24.9536,-29.3876,65.801);
    Vector3 z(0.,0.,2.567);

    int j = 7;

    foo(Ha,j);
    return 0;
}

Результаты:

resAuto = -24.9536, -29.3876,65.801

resVector3 = -24.9536, -29.3876,83.77

Нажмите любую клавишу, чтобы продолжить.,.

Я понимаю, что Eigen делает внутреннюю оптимизацию, которая генерирует разные результаты. Но это похоже на ошибку в Eigen и С++ 11.

Ответ 1

Ключевое слово auto сообщает компилятору "угадать" лучший объект, основанный на правой части =. Вы можете проверить результаты, добавив

std::cout << typeid(resAuto).name() <<std::endl;
std::cout << typeid(resVector3).name() <<std::endl;

до foo (не забудьте включить <typeinfo>).

В этом случае, после создания временного Vector3, вызывается метод operator+, который создает объект CwiseBinaryOp. Этот объект является частью Eigens ленивой оценки (может увеличить производительность). Если вы хотите принудительно произвести оценку (и, следовательно, определение типа), вы можете использовать

const auto resAuto = (Ha + Vector3(0.,0.,j * 2.567)).eval();

вместо вашей строки в foo.

Несколько примечаний:

  • Vector3 идентичен классу Vector3d, определенному в Eigen
  • Вы можете использовать #include <Eigen/Core> вместо #include <Eigen/Geometry>, чтобы включить большинство заголовков Eigen, а также определить определенные вещи там, которые должны быть.