ivanz's blog

By ivanz, history, 3 years ago, In English

I have two structures declared this way:

struct dot {                                                                                            
    int x, y;                                                                                            
};                                                                                            
                                                                                            
                                                                                            
struct pig : dot {                                                                                            
    int z;                                                                                            
}; 

I can declare dot variable like this:

dot a = {1, 100};

But how can I declare pig variable? The only way I found is this:

pig b;                                                                                            
b.x = 1;                                                                                            
b.y = 100;                                                                                            
b.z = 2134;    

Is there any way to do it easier, like with dot variables?
I tried this:

pig b = {1, 100, 2133}

but it doesn't work.
Please, help!

Here's what I was looking for:

struct dot {
    int x, y;
};


struct pig : dot {
    int z;

    pig(int x_, int y_, int z_) : dot{x_, y_}, z{z_} {}
};


pig b{1, 2, 3};
  • Vote: I like it
  • +8
  • Vote: I do not like it

»
3 years ago, # |
Rev. 2   Vote: I like it +5 Vote: I do not like it

You should always provide the error message your getting. Apart from that: works for me.

Maybe your using an older version of C++. Aggregate initilization was improved in C++17.

  • »
    »
    3 years ago, # ^ |
      Vote: I like it -15 Vote: I do not like it
    1. don't use obj = {...}, use obj{...}; I got this from a video about C++ features but don't remember where or why exactly

    2. init lists like that are terrible for knowing which variables got assigned what values, you should use something like {.x = x, .y = y, .a = a} (which doesn't compile in this case and that's good)

    • »
      »
      »
      3 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      Not sure, why that's directed towards me. I just copied the contents of the OP.

      1. The only semantic difference between the two is: the former (so-called copy initialization) does not allow the usage of constructors declared explicit whereas the latter (direct initialization) does. This has let to some inconsistencies in previous versions of the standard (library issue 2193). So the "uniform" initialization can be used more widely. However, the C++ elite is divided on the issue: Bjarne Stroustrup (creator of C++) and Herb Sutter (chairman of the Standard commitee) recommend in their Core Guidelines to use direct initialization as default. Titus Winter and the Google crowd want to the = by default (source). They find copy initialization has the more natural syntax and that uniformity should not be an end to itself.

      2. I don't disagree with that (for non-trivial cases) but we have the same problem with function and template parameters for which C++20 doesn't provide an equivalent solution – other than wrapping everything in a single object or tag types, respectively.

      • »
        »
        »
        »
        3 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        I just put my thoughts into some replies 11 but for function/template arguments, you at least don't have inheritance so there are no questions about "is z the first or last value in the init list?" for sure. I use f(/*name=*/value) for function parameters that need naming, or you can have IDE help you with that.

»
3 years ago, # |
  Vote: I like it +6 Vote: I do not like it

Here's a question for you to think about: what sort of instructions does the syntax of "derived class" correspond to? Keep in mind that a struct is a class and gets default constructors if you don't specify any.

Answer

Lesson: don't use implicit constructors for non-trivial classes.

»
3 years ago, # |
  Vote: I like it +5 Vote: I do not like it

pig b = { { 1, 100 }, 2133 };?

  • »
    »
    3 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    No, it doesn't compile. This implementation works:

    struct dot {
        int x, y;
    };
    
    
    struct pig : dot {
        int z;
    
        pig(int x_, int y_, int z_) : dot{x_, y_}, z{z_} {}
    };
    
    
    pig b{1, 2, 3};
    
    
    • »
      »
      »
      3 years ago, # ^ |
      Rev. 2   Vote: I like it +5 Vote: I do not like it

      Please tell me where you compile and what error is.
      AFAIK, my way must work since C++17.

      Experiment was success on local MSVC++ 2019, wandbox gcc 12 and wandbox clang 13.

      clang
      gcc

      • »
        »
        »
        »
        3 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        You are right. It didn't compile because i used C++14. If you use C++17, everything is ok and your method works.