2015-06-28 10 views
5

Ho ottenuto risultati diversi usando auto e usando Vector sommando due vettori.Risultati errati usando auto con Eigen

Il mio codice:

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

I risultati:

resAuto = -24,9536, -29.3876,65.801

resVector3 = -24,9536, -29.3876,83.77

Press qualsiasi chiave per continuare. . .

Comprendo che Eigen esegue l'ottimizzazione interna che genera risultati diversi. Ma sembra un bug in Eigen e C++ 11.

+1

Se suona come "un bug in Eigen e C++ 11", probabilmente non lo è. Leggere di nuovo la documentazione con attenzione, prestando particolare attenzione ai modelli di espressione. –

+0

Funziona con successo con me con eigen 3.2.2. – user2658323

+0

I modelli di espressione e altre classi che restituiscono tipi di proxy (vettore :: operator [] (size_t)) possono essere sorprendenti se utilizzati con auto. Invece di ottenere la somma dei tuoi vettori ottieni un tipo che memorizza l'espressione della somma dei tuoi due vettori. Questa è un'ottimizzazione del modello che viene spesso utilizzata per matrici live di oggetti di grandi dimensioni. In altre notizie, c'era una proposta per 'operator auto' che avrebbe permesso all'autore della classe Eigen di restituire un Vector3 reale nel tuo caso. Conosco GCC e penso che il clang l'abbia infilato dentro. Forse incidi il tuo 'operatore auto' e vedi. – emsr

risposta

2

La parola chiave auto indica al compilatore di "indovinare" l'oggetto migliore in base al lato destro dello =. È possibile controllare i risultati aggiungendo

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

a foo (non dimenticate di includere <typeinfo>).

In questo caso, dopo la creazione del valore temporaneo Vector3, viene chiamato il metodo operator+, che crea un oggetto CwiseBinaryOp. Questo oggetto fa parte di Eigens lazy evaluation (può aumentare le prestazioni). Se si vuole forzare la valutazione ansioso (e quindi determinazione del tipo), è possibile utilizzare

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

invece della vostra linea in foo.

Alcune note collaterali:

  • Vector3 è identica alla classe Vector3d definita in Eigen
  • È possibile utilizzare #include <Eigen/Core> invece di #include <Eigen/Geometry> includere la maggior parte delle intestazioni Eigen, oltre a certe cose lì che vengono definiti dovrebbe essere.
Problemi correlati