dedução automática de tipo próprio no produto geral

Tenho o seguinte trecho de código (peço desculpas pelo trecho de código um pouco maior, este é o exemplo mínimo ao qual pude reduzir meu problema):

#include <Eigen/Dense>
#include <complex>
#include <iostream>
#include <typeinfo>

// Dynamic Matrix over Scalar field
template <typename Scalar> 
using DynMat = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;

// Dynamic column vector over Scalar field
template <typename Scalar>
using DynVect = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;

// Returns the D x D Identity matrix over the field Derived::Scalar
// deduced from the expression Eigen::MatrixBase<Derived>& A
template<typename Derived>
DynMat<typename Derived::Scalar> Id(const Eigen::MatrixBase<Derived>& A, std::size_t D)
{   
    DynMat<typename Derived::Scalar> result =
            DynMat<typename Derived::Scalar>::Identity(D, D);

    return result;
}

int main()
{
    //using ScalarField = std::complex<double>; // same issue even if I use complex numbers
    using ScalarField = double; // we use doubles in this example

    // A double dynamic matrix (i.e. MatrixXd)
    DynMat<ScalarField> Foo; // used to deduce the type in Id<>()

    // A double dynamic column vector (i.e. VectorXd)
    DynVect<ScalarField> v(4);
    v << 1., 0. , 0. ,0.; // plug in some values into it

    // Make sure that Id(Foo, 4) correctly deduces the template parameters
    std::cout << "Id(Foo, 4) is indeed the 4 x 4 identiy matrix over the ScalarField of "
              << "typeid().name(): " << typeid(ScalarField).name() << std::endl;
    std::cout << Id(Foo, 4) << std::endl; // Indeed the 4 x 4 complex Identity matrix

    // Use auto type deduction for GenMatProduct, junk is displayed. Why?!
    std::cout << std::endl << "Use auto type deduction for GenMatProduct,\
                 sometimes junk is displayed. Why?!" << std::endl;
    auto autoresult = Id(Foo, 4) * v; // evaluated result must be identically equal to v
    for(int i=0; i<10; i++)
    {
            std::cout << autoresult.transpose(); // thought 1 0 0 0 is the result, but NO, junk
            std::cout << " has norm: " << autoresult.norm() << std::endl; // junk
    }

    // Use implicit cast to Dynamic Matrix, works fine
    std::cout << std::endl << "Use implicit cast to Dynamic Matrix, works fine" << std::endl;
    DynMat<ScalarField> castresult = Id(Foo, 4) * v; // evaluated result must be identically equal to v
    for(int i=0; i<10; i++)
    {
            std::cout << castresult.transpose(); // 1 0 0 0, works ok
            std::cout << " has norm: " << castresult.norm() << std::endl; // ok
    }
}

A idéia principal é que a função de modeloId<>() pega uma expressão EigenA como parâmetro, juntamente com um tamanhoDe produz a matriz de identidade sobre o campo escalar da expressãoA. Essa função por si só funciona bem. No entanto, quando eu o uso em um produto Eigen comauto tipo deduzido, como na linhaauto autoresult = Id(Foo, 4) * v, Eu esperaria multiplicar o vetorv pela matriz de identidade, portanto o resultado líquido deve ser uma expressão que, quando avaliada, deve ser identicamente igual av. Mas não é esse o caso, veja o primeirofor loop, sempre que mostro o resultado e calculo sua norma, fico com a maior parte do tempo inútil. Se, por outro lado, lançar implicitamente o produto EigenId(Foo, 4) * v para uma matriz dinâmica, tudo funciona bem, o resultado é avaliado adequadamente.

Eu uso o Eigen 3.2.2 no OS X Yosemite e obtenho o mesmo comportamento estranho tanto no g ++ 4.9.1 quanto no Apple LLVM versão 6.0 (clang-600.0.54) (baseado no LLVM 3.5svn)

PERGUNTA, QUESTÃO:

Eu não entendo o que está acontecendo no primeirofor loop, por que o produto não é avaliado quando usostd::cout, ou mesmo quando eu uso onorm método? Estou esquecendo de algo? Não há aliasing envolvido aqui, e estou realmente intrigado com o que está acontecendo. Eu sei que Eigen usa avaliação lenta e avalia a expressão quando necessário, mas isso não parece ser o caso aqui. Esse problema é extremamente importante para mim, pois tenho muitas funções do mesmo sabor queId<>(), que quando usado emauto expressões deduzidas podem falhar.

O problema ocorre com bastante frequência, mas nem sempre. No entanto, se você executar o programa 3-4 vezes, você definitivamente o verá.

O comando que eu uso para compilar e executá-lo é:

clang++ (g++) -std=c++11 -isystem ./eigen_3.2.2/ testeigen.cpp -otesteigen; ./testeigen

Uma saída típica que obtive em uma execução real é:

Id(Foo, 4) is indeed the 4 x 4 identiy matrix over the ScalarField of typeid().name(): d
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Use GenMatProduct, sometimes junk is displayed. Why?!
1 0 0 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf

Use implicit cast to Dynamic Matrix, works fine
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1

Mesmo se eu usareval() no

  std::cout << autoresult.eval().transpose(); // thought 1 0 0 0 is the result, but NO, junk
  std::cout << " has norm: " << autoresult.eval().norm() << std::endl; // junk

Estou tendo o mesmo comportamento estranho.

questionAnswers(2)

yourAnswerToTheQuestion