Home > OS >  std::transform with variant
std::transform with variant

Time:06-08

I have two vectors: A vector of a type that acts as a union, whose type I can retrieve.
The other vector is a vector of variants of another type.

I want to use std::transform to do a conversion to one of my variant types. However, I receive a compile error that std::transform or rather the lambda can not deduce the return type.

Here is an example:

#include <variant>
#include <vector>
#include <algorithm>
#include <stdexcept>


// third party types
struct fooData {};
struct barData {};
struct baz {
    int foo_or_bar;
    fooData f;
    barData b;

    fooData* asFoo() {
        return &f;
    }

    barData* asBar() {
        return &b;
    }
};

//my types
struct bar {

};
struct foo {

};

//converter
struct converter {

    bar operator()(const barData& b) {
        return bar{};
    }

    foo operator()(const fooData& f) {
        return foo{};
    }
    
};

int main() {
    using entry = std::variant<bar,foo>;
    //vector of third party type
    std::vector<baz> bazzs{};
    //vector of my variant type
    std::vector<entry> target{};

    std::transform(bazzs.begin(),bazzs.end(),std::back_inserter(target), [](baz& bazzer){
        //both foo and bar are part of the variant, but it refuses to compile
        switch(bazzer.foo_or_bar) {
            case 0:
                return converter{}(*(bazzer.asBar()));
            case 1:
                return converter{}(*(bazzer.asFoo()));
            default:
            throw std::runtime_error("ERROR");
        }
    });
}

How can I make this work?

CodePudding user response:

Add a trailing return type specifier to your lambda:

//              vvvvvvvv -- Add This
[](baz& bazzer) -> entry {
    // ...
}

A lambda, like any function, has to return one single type. As it currently stands it returns different types though depending on which case gets chosen: either bar in case 0 or foo in case 1. Since not all code paths return the same type, the compiler can't decide which type the lambda should return unless you tell it.

  • Related