Подтвердить что ты не робот

Может ли анонимный класс использоваться в качестве возвращаемых типов в С++?

Можно ли использовать анонимные классы в С++ в качестве возвращаемых типов?

Я googled, что это может работать:

struct Test {} * fun()
{
}

Но эта часть кода не компилируется, сообщение об ошибке:

новые типы не могут быть определены в обратном типе

На самом деле код не имеет никакого смысла, я просто хочу выяснить, может ли анонимный класс использоваться в качестве возвращаемого типа в С++.

Вот мой код:

#include <typeinfo>
#include <iterator>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>

using namespace std;

int main(int argc, char **argv)
{
    int mx = [] () -> struct { int x, y ; } { return { 99, 101 } ; } ().x ;
    return 0;
}

Я скомпилирую этот код с помощью g++ xx.cpp -std = С++ 0x, компилятор компилирует:

expected primary-expression before '[' token.
4b9b3361

Ответ 1

Примечание. Эти фрагменты кода больше не работают в последних версиях g++. Я скомпилировал их с версией 4.5.2, но версии 4.6.1 и 4.7.0 больше не принимают их.


Вы можете объявить анонимную структуру как возвращаемый тип лямбда-функции в С++ 11. Но это некрасиво. Этот код присваивает значение от 99 до mx:

int mx = [] () -> struct { int x, y ; } { return { 99, 101 } ; } ().x ;

Выход ideone находится здесь: http://ideone.com/2rbfM

В ответ на запрос cheng:

Лямбда-функция - это новая функция в С++ 11. Это в основном анонимная функция. Вот более простой пример лямбда-функции, которая не принимает аргументов и возвращает int:

[] () -> int { return 99 ; }

Вы можете назначить это переменной (для этого вы должны использовать auto):

auto f = [] () -> int { return 99 ; } ;

Теперь вы можете вызвать его так:

int mx = f() ;

Или вы можете называть это напрямую (это то, что делает мой код):

int mx = [] () -> int { return 99 ; } () ;

Мой код просто использует struct { int x, y ; } вместо int. .x в конце - это обычный синтаксис элемента struct, примененный к возвращаемому значению функции.

Эта функция не так бесполезна, как может показаться. Вы можете вызвать функцию более одного раза, чтобы получить доступ к различным членам:

auto f = [] () -> struct {int x, y ; } { return { 99, 101 } ; } ;
cout << f().x << endl ;
cout << f().y << endl ;

Вам даже не нужно дважды вызывать функцию. Этот код делает именно то, что запросил OP:

auto f = [] () -> struct {int x, y ; } { return { 99, 101 } ; } () ;
cout << f.x << endl ;
cout << f.y << endl ;

Ответ 2

Не могут. Как указано в сообщении об ошибке, из ISO/IEC 14882: 2011 8.3.5/9:

Типы не должны определяться в обратном порядке или в параметрах. Тип параметра или тип возвращаемого значения для определения функции не должен быть неполным типом класса (возможно, с квалификацией cv), если определение функции не вложено в спецификацию элемента для этого класса (включая определения в вложенных классах, определенных в классе).

И вы, конечно, не можете назвать существующий анонимный тип как возвращаемый тип в объявлении функции, так как анонимный класс не имеет имени.

Хотя вы можете создать typedef для неназванного класса и использовать его как возвращаемый тип, поскольку имя typedef становится именем типа класса для целей привязки, класс уже не является анонимным.

Ответ 3

struct Test {} * a;
decltype(a) fun() {
  return a;
}

btw, struct Test {} не является анонимной структурой.

Ответ 4

Нет, вы не можете делать подобные анонимные типы на С++.

Однако вы могли бы использовать typedef для присвоения анонимным типам новых имен.

typedef struct
{
    unsigned x;
    unsigned y;
} TPoint;

Ответ 5

Как @Charles публикует довольно много ответов на вопрос, непосредственно цитирующий из спецификации.

Теперь я думаю, почему анонимный тип не может быть возвращаемым типом функции, потому что предположим, что f возвращает анонимный тип, то что бы написать на вызывающем сайте?

?????  obj = f();

Что должно быть написано вместо ????? в приведенном выше коде?

Ответ 6

Ближе всего вы можете дойти до того, чего хотите, в С++ 14:

auto f() { 
    struct {
        int x, y;
    } ret{10,24};
    return ret;
}
int main() {
  printf("%i", f().x);
}

Строка анонимна (ret - это имя переменной, а не имя типа) и возвращается.

Вы можете получить его, если нужно, с помощью

using my_struct = decltype(f());
my_struct another; another.x++;