5

I have a function returning a named struct consisting of two ints, as follows:

struct myStruct {int i; int j;};

myStruct myFunction(int myArg){
    switch (myArg) {
    case 0: return {1,2};
    case 1: return {2,3};
    default: return {4,5};
    }
}

I want to be able to return the appropriately initialised struct from my switch statement. I can do this by declaring a named struct and initialising it, then returning the named struct, but it would be cleaner if I could have the compiler created anonymous structs for me as in my example above - which does not compile. Can this be made to work (legitimately)? Or what is the cleanest way to achieve my goal?

StephenD
  • 231
  • 1
  • 10

2 Answers2

1

This is perfectly valid C++11 code if we look at the draft C++ standard section 6.6.3 The return statement paragraph 2 says:

A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization (8.5.4) from the specified initializer list.

and it provides the following example:

[ Example:
  std::pair<std::string,int> f(const char* p, int x) {
   return {p,x};
 }
—end example ]

we can see from a a live example that it works but it will not work pre- C++11 as we can see from this live example.

If you are using gcc or clang and you can not use C++11 for some reason you have the option of using compound literals as an extension in C++ even though it is a C99 feature and as we can see from this live example gcc warns:

warning: ISO C++ forbids compound-literals [-Wpedantic]

Another option is to add constructors to your struct:

struct myStruct
{
    int i; int j;
    myStruct() : i(0), j(0) {} ;    
    myStruct(int x, int y) : i(x), j(y) {} ;
};

myStruct myFunction(int myArg){
    switch (myArg) {
    case 0: return myStruct(1,2) ;
    case 1: return myStruct(2,3) ;
    default: return myStruct(4,5) ;
    }
}
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
0

Have you considered adding a constructor?

struct myStruct
{
    int i;
    int j;
    myStruct(int x, int y) {i = x; j = y;}
    myStruct() {} // still want this, otherwise "myStruct x;" won't compile
};
myStruct myFunction(int myArg){
    switch (myArg) {
    case 0: return myStruct(1,2);
    case 1: return myStruct(2,3);
    default: return myStruct(4,5);
    }
}
riv
  • 6,846
  • 2
  • 34
  • 63
  • 1
    OP explicitely wants aggregate initializers – Sebastian Hoffmann Nov 26 '13 at 22:17
  • 1
    -1 The OP clearly states he wants aggregate initialization to work, which means `myStruct` must remain an aggregate. Also, your default constructor leaves members uninitialized, and the other one doesn't use initialization lists. – Praetorian Nov 26 '13 at 22:20
  • He states that he wants clean code as opposed to setting up the fields separately in each case clause. So what if the default constructor is empty, simple `struct myStruct{int i;int j;}` doesn't initialize anything either, I don't see anyone getting upset about that. – riv Nov 26 '13 at 22:24
  • 1
    Well, if you value-initialize the aggregate version the data members get zero initialized. With your version, they don't. I would fix the default constructor at the very least. – juanchopanza Nov 26 '13 at 22:26