2010-01-24 10 views
5

tengo un problema con este trozo de código:¿Cómo pasar una fila de boost :: multi_array y std :: vector por referencia a la misma función de plantilla?

#include <boost/multi_array.hpp> 
#include <boost/array.hpp> 
#include <vector> 
#include <iostream> 

template <typename Vec> 
void foo(Vec& x, size_t N) 
{ 
    for (size_t i = 0; i < N; ++i) { 
     x[i] = i; 
    } 
} 

int main() 
{ 
    std::vector<double> v1(10); 
    foo(v1, 5); 
    std::cout << v1[4] << std::endl; 


    boost::multi_array<double, 2> m1; 
    boost::array<double, 2> shape; 
    shape[0] = 10; 
    shape[1] = 10; 
    m1.resize(shape); 
    foo(m1[0], 5); 
    std::cout << m1[0][4] << std::endl; 
    return 0; 
} 

Tratando de compilar con gcc, me sale el error:

boost_multi_array.cpp: In function 'int main()': 
boost_multi_array.cpp:26: error: invalid initialization of non-const reference of type 'boost::detail::multi_array::sub_array<double, 1u>&' from a temporary of type 'boost::detail::multi_array::sub_array<double, 1u>' 
boost_multi_array.cpp:7: error: in passing argument 1 of 'void foo(Vec&, size_t) [with Vec = boost::detail::multi_array::sub_array<double, 1u>]' 

funciona como se espera por impulso :: multi_array cuando cambio el tipo del primer argumento de la función foo de Vec& a Vec, pero luego el std :: vector se pasa por valor, que no es lo que quiero. ¿Cómo puedo lograr mi objetivo sin escribir dos plantillas?

Respuesta

1

El problema es que para NumDims> 1, operator[] devuelve un objeto temporal del tipo template subarray<NumDims-1>::type.

A (no tan agradable) solución alternativa sería el algo como lo siguiente:

typedef boost::multi_array<double, 2> MA; 
MA m1; 
MA::reference ref = m1[0]; 
foo(ref, 5); // ref is no temporary now 

Una alternativa sería la de envolver su aplicación y proporcionar una sobrecarga para el caso de múltiples matrices .... por ejemplo:

(nota: no he visto cómo obtener la sobrecarga de trabajar con boost::multi_array<T,N>::reference, por favor no ponerlo en uso productivo con esta versión detail::;)

template<class T> 
void foo_impl(T x, size_t N) { 
    for (size_t i = 0; i < N; ++i) { 
     x[i] = i; 
    } 
} 

template<class T> 
void foo(T& t, size_t n) { 
    foo_impl<T&>(t, n); 
} 

template<typename T, size_t size> 
void foo(boost::detail::multi_array::sub_array<T, size> r, size_t n) { 
    foo_impl(r, n); 
} 
+0

¿Podría resolverse de forma elegante utilizando boost :: enable_if_c y boost :: traits? –

+0

La línea MA :: reference ref = m1 [0] definitivamente no es concisa sintácticamente, pero no parece agregar una sobrecarga significativa en el tiempo de ejecución para el caso std :: vectorial. Recientemente me encontré con el mismo problema: http://old.nabble.com/-multiarray--problems-passing-views-by-reference-td27039405.html –

+0

@quant_dev: eso también tiene el problema de por qué usar 'boost :: multi_array :: reference' directamente no funciona, no tengo tiempo para investigar más. –

Cuestiones relacionadas