понедельник, 26 октября 2020 г.

[prog.c++] Особенность aggregate initialization в современном C++, о которой я и не подозревал

Некоторое время назад попробовал разобраться с тем, как работает трюк, описанный в статье "Reflection in C++14". И очень долго тупил и не понимал, как же так получается, что попытки увеличивать количество параметров в выражении aggregate initialization ведут к должному результату... Т.е. сперва делается T{a1}, затем T{a1, a2}, затем T{a1, a2, a3} и т.д. И останавливается это все на aN, где N и есть количество полей в структуре T.

А тупил и не понимал потому, что считал, что в выражении aggregate initialization нужно передавать начальные значения для всех полей структуры T. Т.е., если в T четыре поля, то и в aggregate initialization нужно отдать именно четыре значения. Не больше, не меньше. А именно четыре.

Ну и вот оказалось, что в главном-то я и не прав. В aggregate initialization можно отдать и меньше значений. Вот для иллюстрации работающий пример (убедиться можно на wandbox):

#include <iostream>

struct Demo {
    int a_;
    int b_;
    int c_;
    int d_;
};

std::ostream & operator<<(std::ostream & to, const Demo & d) {
    return (to << '(' << d.a_ << ',' << d.b_ << ',' << d.c_ << ',' << d.d_ << ')');
}

int main() {
    {
        Demo d{};
        std::cout << "First: " << d << std::endl;
    }
    {
        Demo d{10};
        std::cout << "Second: " << d << std::endl;
    }
    {
        Demo d{104215};
        std::cout << "Third: " << d << std::endl;
    }
}

Вот уж, что называется, век живи, век учись, а помрешь все равно дураком ;)

2 комментария:

sergegers комментирует...

Это ещё с C пошло.

eao197 комментирует...

@sergegers

Я помню, что в Сях можно было делать что-то вроде char s[10] = {0, 1, 2};
Но вот по поводу C++, когда aggregate initialization разрешили применять к классам/структурам, у меня почему-то осталось убеждение, что количество инициализирующих значений должно совпадать с количеством полей в классе/структуре. А вот почему это убеждение сложилось уже и не вспомнить.