https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92679
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |RESOLVED
Resolution|--- |INVALID
--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Non-preprocessed testcase:
#include <iostream>
#include <typeindex>
#include <functional>
#include <any>
#include <unordered_map>
template <typename TReturn>
struct any_visitor {
using function = std::function<TReturn(std::any &)>;
std::unordered_map<std::type_index, function> functions;
template <typename TArg>
void accept(std::function<TReturn(TArg &)> f) {
functions.insert(std::make_pair(std::type_index(typeid(TArg)),
function([&f](std::any &x) -> TReturn {
return f(std::any_cast<TArg &>(x));
})));
}
TReturn operator()(std::any &x) {
try {
auto function = functions.at(std::type_index(x.type()));
return function(x);
} catch (...) {
throw std::runtime_error("No visitor registered");
}
}
};
int main() {
auto visitor = any_visitor<std::string>();
visitor.accept<int>([](int x) { return std::to_string(x); });
visitor.accept<double>([](double x) { return std::to_string(x); });
visitor.accept<std::string>([](std::string &x) { return x; });
visitor.accept<std::vector<double>>(
[](std::vector<double>&) { return "VECTOR"; });
std::any x;
x = 1;
std::cout << visitor(x) << "\n";
x = 1.;
std::cout << visitor(x) << "\n";
x = std::string("STRING");
std::cout << visitor(x) << "\n";
x = std::vector<double>{0., 1., 2., 3., 4., 5.};
std::cout << visitor(x) << "\n";
}
The bug is here:
void accept(std::function<TReturn(TArg &)> f) {
functions.insert(std::make_pair(std::type_index(typeid(TArg)),
function([&f](std::any &x) -> TReturn {
^^^^
You're binding a reference to a function parameter, which goes out of scope as
soon as the function returns. When you later invoke the std::function it uses a
dangling reference.