es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El uso del operador ‘|’ (pipe) con std::views no se compila.

Después de una desviación en su carrera, estoy intentando ponerme al día con std::views (y la programación funcional en general). Estoy usando el operador ‘|’ (pipe) con std::views::filter en un vector, y estoy confundido por qué algunas estructuras de código se compilan y otras no.

Este código crea un vector de vectores de int, luego los filtra por su suma. He comentado las tres declaraciones que me confunden, las dos primeras de las cuales se compilan y la tercera no.

El error de compilación es:

‘ | ‘: no se encontró el operador que tome un operando izquierdo del tipo ‘std::vector <int, std::allocator=””></int,>> , std::allocator <int, std::allocator=””></int,>> >> > ‘ (o no hay una conversión aceptable)

(Usando MSVC19, compilado con ‘/std:c++latest’)

Estoy confundido por qué esto no se compila mientras que (2) especialmente sí lo hace?

#include
#include
#include

template
auto buildMultiples(const std::vector& base)
{
std::vector<>> vRet;
for(T n= 1; n <= 5; n++)
{
auto v = base;
for (auto& m : v) m *= n;
vRet.push_back(v);
}
return vRet;
}

template
struct sumGreaterThan
{
T _limit{ 0 };

auto operator()(const std::vector<t>& v) {return std::accumulate(v.cbegin(), v.cend(), 0) > _limit;}

};

int main()
{
using namespace std;
vector nums{1,2,3,4,5,6,7,8,9};

auto mults = buildMultiples(nums);

for (auto& m : buildMultiples(nums)) {} //1. Compila

sumGreaterThan<int> sumFilter{ 10 };

auto vecs = buildMultiples(nums);
for (auto& m : vecs | views::filter(sumFilter)) {} //2. Compila

for (auto& m : buildMultiples(nums) | views::filter(sumFilter)) {} //3. ¡Error de compilación!

for (auto vecs = buildMultiples(nums); auto& m : vecs | views::filter(sumFilter)) {} // 4. Compila. Gracias @Aryter

}

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la cual la tercera declaración no compila es porque el operador pipe (|) tiene una precedencia mayor que el operador punto (.). Esto significa que buildMultiples(nums) | views::filter(sumFilter) es tratado como (buildMultiples(nums) | views::filter)(sumFilter), lo cual no es lo que queremos. Queremos filtrar el resultado de buildMultiples(nums) y no filtrar buildMultiples(nums) en sí.

    Para arreglar esto, necesitamos agrupar la expresión buildMultiples(nums) utilizando paréntesis de esta manera:

    for (auto& m : (buildMultiples(nums) | views::filter(sumFilter))) {}
    

    Esto filtrará correctamente el resultado de buildMultiples(nums) y el código compilará.

    Alternativamente, podemos asignar el resultado de buildMultiples(nums) a una variable y luego filtrar la variable de esta manera:

    auto vecs = buildMultiples(nums);
    for (auto& m : vecs | views::filter(sumFilter)) {}
    

    Esto también filtrará correctamente el resultado y el código compilará.

Comments are closed.