Возврат анонимной структуры - PullRequest
1 голос
/ 08 июля 2019

Кажется, вы можете вернуть неназванный struct таким образом:

auto foo() {
    struct {
        int bar;

        int square() {
            return bar * bar;
        }
    } a { 7 };
    return a;
}

Есть ли способ сделать это без избыточного имени переменной a, то есть анонимно?

Ответы [ 7 ]

5 голосов
/ 08 июля 2019

Нет, это невозможно.

Самое близкое, что вы можете получить, это использовать приведение в функциональном стиле для создания временного объекта и использовать scoped-инициализатор в стиле C99;GCC допускает это в режиме C ++ как расширение:

#include <iostream>
#include <string>

auto foo() {
    return (struct {
        int bar;

        int square() {
            return bar * bar;
        }
    }) { 7 };
}

… но это не переносимо (и будет предупреждать).

Без скобок вокруг 7 расширение не запускаетсяи вы вернулись к стандартному коду, в котором недопустимо определять тип в приведении .

Вместо написания тупого кода присвойте вашему типу имя и присвойте свой объектимя.Ваши читатели будут вам благодарны.

5 голосов
/ 08 июля 2019

Для начала C ++ не определяет анонимные структуры. Я думаю, что вы имеете в виду безымянную структуру.

В соответствии со стандартом C ++ оператор return определяется как (8.6 операторов Jump)

return expr-or-braced-init-listopt ;

Таким образом, вы не можете использовать объявление в операторе возврата. Если это так, то вам нужно предварительно объявить объект типа структуры, который будет возвращен.

3 голосов
/ 08 июля 2019

Я понятия не имею, в чем смысл этого упражнения, поэтому вот ответ, который технически делает то, что вы просите:

auto helper()
{
    struct {
        int x;
    } a {0};
    return a;
}

decltype(helper()) foo()
{
    return {8};
}

https://godbolt.org/z/zA8C1V

  • Структура не имеет имени.

  • foo не возвращает именованную переменную.

Конечно, это просто смешно - можно просто назвать структуру вместо этого decltype дурачества.

2 голосов
/ 08 июля 2019

Ни один из

struct {/*...*/} foo() { // Illegal
    return {/*...*/};
}
auto foo() {
    return struct { /*...*/ } { /*...*/ }; // Illegal
}
template <typename T = struct { /*...*/ }> // Illegal
T foo() {
    return { /*...*/ };
}

не является допустимым.

Вы должны, по крайней мере, иметь именованный тип или именованный экземпляр.

Лямбда позволяет не иметь ни того, ни другого, но вы можете только захватить и определить ее operator():

auto foo() {
    return [/*...*/](/*...*/) { /*...*/ }; // Legal
}
0 голосов
/ 08 июля 2019

Возвращение анонимной структуры

В C ++ не существует такой вещи, как анонимная структура. Этого достаточно, чтобы сделать это невозможным.

Существует ограниченный способ возврата объекта анонимного типа из функции: возврат лямбды.

auto make_square_function() {
    return [bar = 7]() {
        return bar * bar;
    };
}

Лямбды намного более ограничены, чем обычные классы. Элементы (захваты) инкапсулированы и не могут быть названы извне лямбда-выражения, и нет никаких функций-членов, кроме перегрузки вызова функции.

В любом случае можно сделать это без избыточного имени переменной a

Только если вы дадите классу имя:

struct Squarer {
    int bar;

    int square() {
        return bar * bar;
    }
};

auto foo() {
    return Squarer{7};
}

Возвращение экземпляра безымянного класса возможно только путем определения переменной.

0 голосов
/ 08 июля 2019

Просто для удовольствия, еще одно решение «определи переменную в другом» (на основе ответа Макса Лангофа) * ​​1001 *

auto foo ()
 {
   return []{ struct{int bar;} a {7}; return a; }();
 }
0 голосов
/ 08 июля 2019

Нет, потому что вам нужно вернуть экземпляр объекта, в данном случае a.

Возвращенный объект должен существовать где-то в памяти, вы не можете просто вернуть определение класса.

В вашем примере вы не возвращаете анонимную структуру, но вы возвращаете экземпляр этой структуры.

...