2015-06-28 13 views
5

Otrzymałem różne wyniki używając auto i używając Vector podczas sumowania dwóch wektorów.Nieprawidłowe wyniki z użyciem automatu z Eigenem

Mój kod:

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

Wyniki:

resAuto = -24,9536, -29.3876,65.801

resVector3 = -24,9536, -29.3876,83.77

Prasa dowolny klucz, aby kontynuować. . .

Rozumiem, że Eigen dokonuje wewnętrznej optymalizacji, która generuje różne wyniki. Ale wygląda na błąd w Eigen i C++ 11.

+1

Jeśli brzmi jak "błąd w Eigen i C++ 11", prawdopodobnie tak nie jest. Przeczytaj uważnie dokumentację, zwracając szczególną uwagę na szablony wyrażeń. –

+0

Z powodzeniem działa dla mnie z własnym 3.2.2. – user2658323

+0

Szablony wyrażeń i inne klasy zwracające typy proxy (wektor :: operator [] (size_t)) mogą być zaskakujące, gdy są używane z auto. Zamiast zbierać sumę twoich wektorów, dostajesz typ, który przechowuje wyrażenie sumy twoich dwóch wektorów. Jest to optymalizacja szablonu, która jest często używana w przypadku macierzy na żywo dużych obiektów. W innych wiadomościach pojawiła się propozycja "operatora auto", która pozwoliłaby autorowi klasy Eigen zwrócić faktyczny Vector3 w twoim przypadku. Znam gcc i myślę, że klang w to wkradł. Może włamać się do twojego "auta operatora" i zobaczyć. – emsr

Odpowiedz

2

Słowo kluczowe auto mówi kompilatorowi "odgadnąć" najlepszy obiekt oparty na prawej stronie =. można sprawdzić wyniki dodając

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

do foo (nie zapomnij podać <typeinfo>).

W tym przypadku po wywołaniu tymczasowego Vector3 wywoływana jest metoda operator+, która tworzy obiekt CwiseBinaryOp. Ten obiekt jest częścią Eigens lazy evaluation (może zwiększyć wydajność). Jeśli chcesz, aby wymusić chętny oceny (a więc określenie typu), można użyć

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

zamiast linii w foo.

Kilka uwag niepożądane:

  • Vector3 jest identyczna z klasą Vector3d określonym w Eigen
  • Można użyć #include <Eigen/Core> zamiast #include <Eigen/Geometry> obejmować większość nagłówków EIGEN, plus pewne rzeczy się zdefiniowane tam powinno być.
Powiązane problemy