Здравствуйте, diez_p, Вы писали:
_>в шарпах ref/out,
В шарпах, как и у всех — туплы. И destructuring assignment тоже есть.
(int, string, int*) MyFunc()
{
return (5, "ssssss", malloc(...));
}
var (x, y, z) = MyFunc();
Здравствуйте, Hоmunculus, Вы писали:
H>Исторически сложилось, что функция возвращает одно значение. В return.
В одном значении может быть что-то, что хранит в себе юнион с типом, или коллекцию значений.
Даже в голом C можно вернуть структуру. И нет смысла избегать этого, более того: возврат структур
по-значению для компилятора легче в плане генерации оптимального кода, чем работа с указателями.
Просто на некоторых старинных рахитектурах возврат структуры по-значению требовал выкрутасов
с копированием на стеке и этого избегали. Сейчас везде как правило возврат структуры компилятором
преобразуется в ту же передачу по-ссылке (на структуру которая будет возвращена, и память под
которую аллоцирована на стеке вызывающей функции), но при этом отлично оптимизируется в регистры
при случае.
H>Почему не придумали типа такого?
H>H>int/string/int* MyFunc()
H>{
H> int res1 = 5;
H> string res2 = “ssssss”;
H> int* res3 = (int*)malloc…;
H> return1 res1;
H> return2 res2;
H> return3 res3;
H>}
H>Print(MyFunc()2);
H>int b = MyFunc()1 + 6;
H>
struct Eklmn { int x; char *y; float z; } my_func(...)
{
...
if (...)
return (struct Eklmn){.x = 100500};
if (...)
return (struct Eklmn){.y = "xaxaxa");
...
}
...
printf("%s", my_func(...).y);
int b = my_func(...).x + 6);
...
Если нужен std::variant, то можно сделать что-то вроде:
struct NedoVariant
{
enum {
VariantInt, VariantString, VariantFloat...
} type;
union {
int x;
const char *y;
float z;
...
};
};
Соответственно, устанавливаем/читаем поле type и другое соответствующее ему поле.