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.