1

It seems you can return an unnamed struct this way:

auto foo() {
    struct {
        int bar;

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

Is there anyway to do this without the redundant variable name a, thus anonymously?

7 Answers7

5

I have no idea what the point of this exercise is, so here is an answer that technically does what you ask for:

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

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

https://godbolt.org/z/zA8C1V

  • The struct is unnamed.

  • foo does not return a named variable.

Of course this is straight up ridiculous - one would just name the struct instead of this decltype tomfoolery.

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
  • 1
    This is equally redundant, since `a` is used in a similar redundant manner. –  Jul 08 '19 at 11:31
  • 1
    Great! Any comment on the possible differences between `decltype(helper())` and `invoke_result` for someone not so knowledgeable? – Fureeish Jul 08 '19 at 11:32
  • 5
    @Fureeish The main difference is the amount of laziness I'd have to overcome to type it out for this not-exactly-serious answer. – Max Langhof Jul 08 '19 at 11:33
  • @super what redundancy are you talking about? – Timo Jul 08 '19 at 11:33
  • @super It's hard to optimize the code for your vaguely specified measure of redundancy. I don't expect this answer to be useful, but I mainly don't understand how _any_ answer would be useful because I don't see the point of it. What do you gain from returning an unnamed struct over putting your function's interface into words? All I see is code obfuscation (in which case my answer is falls in line)... – Max Langhof Jul 08 '19 at 11:36
  • @Max Langhof This answer is for one single specific struct, and for each struct you wanna do it for, you gotta rewrite the same code containing two `a`s. A simple "No" or "You can't do it" answer would be more satisfying. –  Jul 08 '19 at 11:39
  • @super Is there any reason you ever want to do that? Sounds like a XY problem to me. – Timo Jul 08 '19 at 11:41
  • @super Your question never specified this has to be done for multiple/many structs. This is exactly the "**vaguely specified** measure of redundancy" I'm talking about. If you tell us what problem are you trying to solve we might be able to give a better answer. – Max Langhof Jul 08 '19 at 11:41
  • @super That was suggested/posted by Timo [here](https://stackoverflow.com/questions/56933382/returning-anonymous-struct/56933962?noredirect=1#comment100408162_56933382). Jonathan Wakely himself replied that [that's a C99 feature that GCC allows in C++ as an extension](https://stackoverflow.com/questions/56933382/returning-anonymous-struct/56933962?noredirect=1#comment100408504_56933382). It's not part of the C++ standard and unsupported by most compilers. – Max Langhof Jul 08 '19 at 15:56
5

For starters C++ does not define anonymous structures. I think you mean an unnamed structure.

According ro the C++ Standard the return statement is defined like (8.6 Jump statements)

return expr-or-braced-init-listopt ;

So you may not use a declaration in the return statement. If so then you need prelimary to declare an object of the structure type that will be returned.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • There is also [\[dcl.fct\] 9.2.3.5 §12](http://eel.is/c++draft/dcl.fct#12), which states _" Types shall not be defined in return or parameter types."_ And I don't know if auto (in OP's code) legally circumvents that. – nada Jul 08 '19 at 11:46
  • @nada _"And I don't know if auto legally circumvents that"_ no it doesn't. – Timo Jul 08 '19 at 11:48
  • 3
    `I think you mean an unnamed structure.` I don't think so. They demonstrate how returning an unnamed structure works; they specifically want to get rid of the variable i.e. they want the struct to be anonymous. Even in C that has anonymous structures, they only exist as members though. – eerorika Jul 08 '19 at 11:49
4

No, this is not possible.

The closest you can get is to use a functional-style cast to create a temporary, and use a C99-style scoped-initialiser; GCC allows this in C++ mode, as an extension:

#include <iostream>
#include <string>

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

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

… but this is not portable (and will warn).

Without the braces around 7 the extension is not triggered, and you're back to standard code, in which it is illegal to define a type in a cast.

Instead of writing obtuse code, give your type a name and give your object a name. Your readers will thank you.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

None of

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

are legal.

You have to, at least, have a named type, or a named instance.

Lambda allows to have neither, but you can only capture and define its operator():

auto foo() {
    return [/*...*/](/*...*/) { /*...*/ }; // Legal
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • @super: indeed, it would be an other possible syntax, but as already states in question comment, compound literals are not standard C++ but an extension. – Jarod42 Jul 08 '19 at 15:52
0

Returning anonymous struct

There is no such thing as anonymous struct in C++. That's enough to make it impossible.

There is a - limited - way of returning an object of anonymous type from a function: Returning a lambda.

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

Lambdas are much more limited than general classes though. The members (captures) are encapsulated and cannot be named from the outside of the lambda and there are no member functions other than the function call overload.

Is there anyway to do this without the redundant variable name a

Only if you give the class a name:

struct Squarer {
    int bar;

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

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

Returning an instance of unnamed class is only possible by defining a variable.

eerorika
  • 232,697
  • 12
  • 197
  • 326
-1

Just for fun, another define-the-variable-in-another-function solution (taking inspiration from Max Langhof's answer)

auto foo ()
 {
   return []{ struct{int bar;} a {7}; return a; }();
 }
max66
  • 65,235
  • 10
  • 71
  • 111
-2

No, because you need to return an instance of an object, in this case a.

The returned object has to exist somewhere in memory, you can't just return a class definition.

In your example, you don't return an anonymous struct, but you return an instance of that struct.

A.Franzen
  • 725
  • 4
  • 10
  • Good answer. Do you have sources to back it up? –  Jul 08 '19 at 11:20
  • The need to return an instance of something does not imply that you have to return a named variable. – Max Langhof Jul 08 '19 at 11:22
  • 1
    The reason is "wrong", `return std::string{}` doesn't return a named instance for example. `return struct {/*...*/}{/*..*/};` might have been a possible syntax to the OP (but it isn't legal). – Jarod42 Jul 08 '19 at 11:22
  • return puts the return value on the stack, whatever it is, for the simple types like int, double etc. its the value itself. For complex datatypes its the pointer to an instance of that type. With just a struct there is no instance, and hence you cant put a value on the stack. And the only way to get an instance of a struct is by declaring a variable of that type. – A.Franzen Jul 08 '19 at 11:29
  • 1
    "*For complex datatypes its the pointer to an instance of that type*" - that is also incorrect. What's a *complex datatype*? Why you can't have one like that on the stack? – Fureeish Jul 08 '19 at 11:30
  • A complex datatype is a struct or a class. Btw, with a class you CAN construct an anonymous object by just calling the constructor....it's called a temporary object. – A.Franzen Jul 08 '19 at 11:31
  • Then what you said is simply not true. Objects of user defined types can live on the stack. Why do you claim that they cannot? – Fureeish Jul 08 '19 at 11:33
  • I don't. I just say that return needs an actual value. Thus you have to suply one. And you can't create an instance of a struct without declaring a variable of that struct-type. – A.Franzen Jul 08 '19 at 11:36
  • 1
    @A.Franzen an unnamed instance (what you call temporary object) is not the same as an unnamed type. – Timo Jul 08 '19 at 11:36
  • Once again, return returns VALUES not types. You can't return a type, only a value. – A.Franzen Jul 08 '19 at 11:37
  • OP is talking about returning an unnamed instance of an unnamed type. At least that's how I understand the question. – Timo Jul 08 '19 at 11:38
  • 1
    _" And the only way to get an instance of a struct is by declaring a variable of that type."_ That is simply incorrect, as has been explained several times now. `std::string{}` is an expression that creates a temporary object (i.e. instance) of type `std::string`. What exactly do you think the `at` method operates on in `std::string{"abc"}.at(0)` if not an instance of `std::string`? – Max Langhof Jul 08 '19 at 11:45
  • 1
    Nobody has suggested or recommended returning a type. – Lightness Races in Orbit Jul 08 '19 at 11:48
  • _"Btw, with a class you CAN construct an anonymous object by just calling the constructor....it's called a temporary object"_ No, despite the appearance of functional-cast notation, you never "call the constructor" - syntax to do so does not exist. – Lightness Races in Orbit Jul 08 '19 at 11:49
  • _"For complex datatypes its the pointer to an instance of that type"_ Incorrect; no pointers are involved. – Lightness Races in Orbit Jul 08 '19 at 11:50
  • 1
    @LightnessRacesinOrbit _"you never "call the constructor""_. This is probably a bug but msvc [allows it](https://godbolt.org/z/ihY_Cy). – Timo Jul 08 '19 at 11:53
  • @Timo Hah, figures...([some exploration here](https://stackoverflow.com/questions/2494471/c-is-it-possible-to-call-a-constructor-directly-without-new#comment65005497_38779256)) – Lightness Races in Orbit Jul 08 '19 at 12:31