CRTP: Problema dependiente del compilador con Expression Template

Incurrí en un problema dependiente del compilador con el siguiente código (almacenado en crtp.cc):

#include <vector>
#include <cassert>
#include <iostream>

template < class Derived >
class AlgebraicVectorExpression {
public:
  typedef std::vector<double>::size_type  SizeType;
  typedef std::vector<double>::value_type ValueType;
  typedef std::vector<double>::reference  ReferenceType;

  SizeType size() const {
    return static_cast<const Derived&>(*this).size();
  }

  ValueType operator[](SizeType ii) const {
    return static_cast<const Derived&>(*this)[ii];
  }

  operator Derived&() {
    return static_cast<Derived&>(*this);
  }

  operator const Derived&() const {
    return static_cast< const Derived& >(*this);
  }
};

template< class T1, class T2>
class AlgebraicVectorSum : public AlgebraicVectorExpression< AlgebraicVectorSum<T1,T2> > {
  const T1 & a_;
  const T2 & b_;

  typedef typename AlgebraicVectorExpression< AlgebraicVectorSum<T1,T2> >::SizeType  SizeType;
  typedef typename AlgebraicVectorExpression< AlgebraicVectorSum<T1,T2> >::ValueType ValueType;
public:

  AlgebraicVectorSum(const AlgebraicVectorExpression<T1>& a, const AlgebraicVectorExpression<T1>& b) :
    a_(a), b_(b)  {
    assert(a_.size() == b_.size());
  }

  SizeType size() const {
    return a_.size();
  }

  ValueType operator[](SizeType ii) const {
    return (a_[ii] + b_[ii]);
  }

};

template< class T1, class T2>
const AlgebraicVectorSum<T1,T2>
operator+(const AlgebraicVectorExpression<T1>& a, const AlgebraicVectorExpression<T2>& b) {
  return AlgebraicVectorSum<T1,T2>(a,b);
}

class AlgebraicVector : public AlgebraicVectorExpression<AlgebraicVector>{
  std::vector<double> data_;

public:
  SizeType size() const {
    return data_.size();
  }

  ValueType operator[](SizeType ii) const {
    return data_[ii];
  }

  ValueType& operator[](SizeType ii) {
    return data_[ii];
  }

  AlgebraicVector(SizeType n) : data_(n,0.0) {
  };

  template< class T>
  AlgebraicVector(const AlgebraicVectorExpression<T>& vec) {
    const T& v = vec;
    data_.resize(v.size());
    for( SizeType idx = 0; idx != v.size(); ++idx) {
      data_[idx] = v[idx];
    }
  }
};

int main() {

  AlgebraicVector x(10);
  AlgebraicVector y(10);
  for (int ii = 0; ii != 10; ++ii)
    x[ii] = y[ii] = ii;    

  AlgebraicVector z(10);
  z = x + y;

  for(int ii = 0; ii != 10; ++ii)
    std::cout << z[ii] << std::endl;
  return 0;
}

e hecho, cuando lo compilo con:

$ g++ --version
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ -O0 -g crtp.cc

Yo obtengo

$ ./a.out 
0
2
4
6
8
10
12
14
16
18

cuál es el comportamiento esperado. Cuando uso icpc:

$ icpc --version
icpc (ICC) 12.1.0 20110811
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.    
$ icpc -g -O0 crtp.cc

Obtuve en cambio unaSegmentation fault. Corriend

valgrind --tool=memcheck ./a.out

points a la línea 29 en las fuentes

AlgebraicVectorExpression<AlgebraicVector>::operator AlgebraicVector const&() const (crtp.cc:29)

Como soy bastante nuevo en C ++ y pasé bastante tiempo buscando un error sin ningún resultado, me gustaría pedir la opinión de alguien más experimentado para entender si este problema se debe a algún error que introduje (como espero) o a un error del compilador.

Edita: Cambié el código como está ahora, después de la respuesta de Mike Seymour. Ahora no recibo advertencias del compilador, pero sigo teniendo el mismo comportamiento que antes (con la misma respuesta valgrind). ¿Alguien intentó compilar con Intel?

Edita: Traté de compilar el código en la Plantillas de expresión página de Wikipedia. Obtuve el mismo comportamiento exacto que con el ejemplo que proporcioné.

Edita: He investigado el problema más a fondo y parece que compilar con Intelicpc el operado

operator const Derived&() const {
    return static_cast< const Derived& >(*this);
  }

se llama recursivamente a sí mismo. Una solución alternativa que encontré es sustituir este operador con un método:

const Derived& get_ref() const {
    return static_cast< const Derived& >(*this);
  }

y modifique los constructores de las diversas clases en consecuencia. ¿Alguien puede decir cuál de estos dos comportamientos es correcto posiblemente señalando el estándar para explicar eso?

Respuestas a la pregunta(2)

Su respuesta a la pregunta