Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

std::transform with variant

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#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?

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading