Cómo pasar una fila de impulso :: multi_array y std :: vector por referencia a la misma función de plantilla?

StackOverflow https://stackoverflow.com/questions/2129235

Pregunta

Tengo un problema con este trozo de código:

#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>]'

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

¿Fue útil?

Solución

El problema es que para NumDims> 1 , vuelve operator[] 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 vi cómo obtener la sobrecarga de trabajo 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);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top