Search code examples
c++implicit-conversionstd-rangesc++23

ranges::to() error: conversion to non-scalar type requested


#include <ranges>
#include <algorithm>
#include <vector>
using namespace std;

struct Edge{int from, to;};

const vector<int> v1 = {1, 1} , v2 = {2,2};

vector<Edge> v3 = views::zip( v1, v2) | ranges::to<vector>();

compilation using g++14.

prog.cc:10:38: error: conversion from 'vector<std::tuple<int, int>,allocator<std::tuple<int, int>>>' to non-scalar type 'vector<Edge,allocator>' requested

Can this be fixed without doing (painfully verbose):

#include <ranges>
#include <algorithm>
#include <vector>
using namespace std;

int main(){

struct Edge{int from, to;};

const vector<int> v1 = {1, 1} , v2 = {2,2};

vector<Edge> v3 = views::zip( v1, v2) | views::transform([](const auto arg){const auto [a, b]=arg; return Edge{a,b};}) | ranges::to<vector>();

}

Solution

  • With C++23 comes zip_transform which could reduce it to this

    #include <ranges>
    #include <vector>
    #include <iostream>
    
    //using namespace std; //unlearn this
    
    int main()
    {
    
        struct Edge
        {
            static Edge Create(int f,int t)
            {
                return Edge{f,t};
            }
    
            int from;
            int to;
        };
    
        const std::vector<int> v1 = { 1, 2 };
        const std::vector<int> v2 = { 3, 4 };
        
        auto edges = std::views::zip_transform(Edge::Create,v1,v2) | std::ranges::to<std::vector>();
    
        for(const auto& edge : edges)
        {
            std::cout << "edge : from " << edge.from << " to" << edge.to << "\n";
        }
    
        return 0;
    }