cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

Главный (primary) конструктор для класса #360

Open apolukhin opened 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +0, -7 Автор идеи: Роман Попов

Предлагаю добавить в C++ primary constructor по аналогии с Kotlin и Scala.

Попытка решить две проблемы:

1) В C++ 11 добавили инициализацию полей класса, но нет удобного способа передать параметры из конструктора

2) Часто бывает так что объекты требуют дополнительной инициализации после создания. Удобно если эта инициализация расположена в коде рядом с объявлением поля.

Пример синтаксиса для C++ (взят из Kotlin):

class ClassWithPrimaryCtor (int xInit, int yInit, const string& sInit)  {
    int x = xInit;
    int y = yInit;

    Widget w;
    init {
        w.setName(sInit);
        w.setDims(x,y);
    }
};

Прототип для пояснения семантики :

template <unsigned UNIQUE>
struct InitInvoker {
    template <typename T>
    InitInvoker(T && f) { f(); }
};

#define init InitInvoker<__LINE__> __init_##__LINE__ = [this]

class PrimaryCtor {
public:
    int xInit;
    int yInit;
    const std::string &sInit;

    PrimaryCtor(int xInit, int yInit, const std::string &sInit)
    : xInit(xInit), yInit(yInit), sInit(sInit) {}
};

class ClassWithPrimaryCtor : protected PrimaryCtor {
public:
    ClassWithPrimaryCtor(int xInit, int yInit, const std::string &sInit)
    : PrimaryCtor(xInit, yInit, sInit) {}

private:
    int x = xInit;
    int y = yInit;

    Widget w;
    init {
        w.setName(sInit);
        w.setDims(x,y);
    };
};
apolukhin commented 3 years ago

yndx-antoshkka, 25 сентября 2018, 12:34 Уже есть возможность из одного конструктора вызывать другой. Так что ваша идея уже внедрена, только без init и с явной передечей параметров.

Роман Попов, 25 сентября 2018, 16:36 Ну так идея именно в том чтобы разрешить использовать параметры конструктора в in-class инициалзицации. Где в C++ эта идея уже внедрена? Да, init наверное можно сделать в C++20 с помощью no_unique_address

Роман Попов, 25 сентября 2018, 17:37 Нашёл ещё одну причину почему это полезно: Унификация compile-time и run-time интерфейсов. Пример:

template <unsigned RPTR_W = 10>
class MyFIFO {
public:
    MyFIFO(unsigned WPTR_W = 10) {}

private:

    sc_int rptr{RPTR_W}; // OK!
    sc_int wptr{WPTR_W}; // Compile Error!
    sc_int xptr{WPTR_W + WPTR_W}; // Compile Error!
};