We have following code(it's more complicated ofc, I tried to make a minimal example).
#include <iostream>
#include <vector>
#include <string>
#include <memory>
template<typename T>
struct use_type
{
use_type(T& v) : value(v) {}
T& value;
};
template<typename T>
use_type<T> use(T& value) { return use_type<T>(value); }
template<typename T>
use_type<T> use(const T& value) { return use_type<T>(const_cast<T&>(value)); }
template<typename T>
struct printer_helper
{
void use(const use_type<T>& use) { uses.push_back(use); }
void final_action()
{
for (const auto& use : uses)
{
std::cout << use.value.size() << std::endl;
for (const auto& v : use.value)
{
std::cout << v << ",";
}
std::cout << std::endl;
}
}
std::vector<use_type<T>> uses;
};
template<typename T>
struct printer
{
printer() { helper = new printer_helper<T>(); }
printer<T>& operator , (const use_type<T>& t)
{
helper->use(t);
return *this;
}
~printer()
{
helper->final_action();
delete helper;
}
printer(const printer&) = delete;
printer& operator =(const printer&) = delete;
printer(printer&&) = default;
printer& operator =(printer&&) = default;
printer_helper<T>* helper;
};
template<typename T>
struct printer_creator
{
printer<T> operator << (const char*) { return {}; }
};
int main()
{
using vec = std::vector<std::string>;
{
/*vec v1{"abc", "bcd"};
vec v2{"new", "old", "real"};*/
printer_creator<vec> p;
p << "", use(vec{"abc", "bcd"}), use(vec{"new", "old", "real"});
//p << p, use(v1), use(v2);
}
}
This code works perfectly fine on g++ before g++-11. With g++-11 it's either segfault or trash in the output. Is it UB? And if yes, probably you can tell me, which gcc change makes it fail and quotes from standard if possible?
Live examples: