2010-06-22 8 views
5

< Actualización > Como de costumbre para mí, la pregunta era incorrecta. La pregunta real es: ¿por qué transform_iterator no usa la metafunción result_of <> convencional para determinar el tipo de devolución, en lugar de acceder a UnaryFunc :: tipo_de_resultado directamente? Publicó una respuesta con un trabajo alrededor. </actualización >¿Cómo usar una expresión de Fénix con boost :: transform_iterator?

Específicamente, ¿hay una manera de hacer una expresión Phoenix exponer un tipo result_type como se esperaba para el concepto std :: unary_function? boost :: transform_iterator parece esperar esto, y de mirar el src de él, no veo una solución simple.

Aquí hay un código que reproduce el problema que he estado teniendo:

#include <boost/iterator/transform_iterator.hpp> 
#include <boost/spirit/home/phoenix.hpp> 
#include <numeric> 
#include <iostream> 

using namespace boost::phoenix; 
using namespace boost::phoenix::arg_names; 

int main(void){ 
    int i[] = {4,2,5,3}; 

    std::cout << 
     std::accumulate(
     boost::make_transform_iterator(i, _1*_1), 
     boost::make_transform_iterator(i+4, _1*_1), 
     0 
    ) << std::endl; 

    return 0; 
} 

La parte relavent del mensaje de error de compilación esto es (gcc 4.3.4, impulsar 1.43):

/usr/include/boost/iterator/transform_iterator.hpp:43: error: no type named ‘result_type’ in ‘struct boost::phoenix::actor<... 

Tengo el mismo problema con boost :: lambda (falta result_type). Pensé que había visto un uso similar para make_transform_iterator y lambda en el pasado, ahora me pregunto si acabo de imaginarlo.

¿Hay una envoltura provista o algún otro mecanismo en fénix o lambda para exponer result_type?

Respuesta

4

Parece que esto está solucionado en el boost trunk (consulte la línea 51, result_of<> en lugar de un UnaryFunc::result_type indirecto). Entonces esto no debería ser un problema en 1.44 y más.

Aquí hay una solución para impulsar < 1.44. La creación de instancias transform_iterator tiene acceso a UnaryFunc::result_type solo si no se proporciona el parámetro de plantilla Reference. Entonces, un truco es reemplazar make_transform_iterator con una versión que llame a la función result_of <> meta en el UnaryFunc y use el resultado para el parámetro de la plantilla de referencia.

#include <boost/iterator/transform_iterator.hpp> 
#include <boost/utility.hpp> 
#include <iterator> 

template <class UnaryFunc, class Iterator> 
boost::transform_iterator< 
    UnaryFunc, 
    Iterator, 
    typename boost::result_of< 
     UnaryFunc(typename std::iterator_traits<Iterator>::value_type) 
    >::type 
> 
make_trans_it(Iterator it, UnaryFunc fun){ 
    return 
     boost::transform_iterator< 
     UnaryFunc, 
     Iterator, 
     typename boost::result_of< 
      UnaryFunc(typename std::iterator_traits<Iterator>::value_type) 
     >::type 
     >(it, fun); 
}; 
Cuestiones relacionadas