ПрограммированиеФорумОбщее

constexpr инициализация

#0
12:30, 6 авг 2019

Я хочу наследоваться от С-style структуры в third-party library и сделать её инициализацию в стиле RAII константами времени компиляции. Данный код отлично компилируется 17-ой студией:

#include <iostream>

struct CStruct
{
    int i;
    float f;
};

class MyClass : public CStruct
{
public:
    constexpr MyClass(int inI, float inF)
    {
        i = inI;
        f = inF;
    }
};

constexpr MyClass obj(5, 10.f);

int main()
{
    std::cout << obj.i << ", " << obj.f << std::endl;
}

Но это не работает в GCC. GCC считает constexpr только следующий вариант кода:

#include <iostream>

class MyClass
{
public:
    int i;
    float f;
    
public:
    constexpr MyClass(int inI, float inF):
        i(inI),
        f(inF)
    {
    }
};

constexpr MyClass obj(5, 10.f);

int main()
{
    std::cout << obj.i << ", " << obj.f << std::endl;
}


global constexpr initialization

Очевидно что с сишной библиотекой я никоим образом не смогу так сделать, что очень обидно, т. к. по сути инициализация времени компиляции, но C++ не позволяет это сделать. Как поступить, отказаться от constexpr или сделать так чтобы студия генерировала constexpr код и сделать non-constexpr для других компиляторов?

#1
14:29, 6 авг 2019

Вот рабочий код, работает под гцц

#include <iostream>

struct CStruct
{
    int i;
    float f;
};

class MyClass : CStruct
{
public:
    int i;
    float f;
    
public:
    constexpr MyClass(int inI, float inF) : CStruct{},
        i(inI),
        f(inF)
    {
    }
};

constexpr MyClass obj(5, 10.f);

int main()
{
    std::cout << obj.i << ", " << obj.f << std::endl;
}
#2
14:30, 6 авг 2019

v1c
>Очевидно что с сишной библиотекой я никоим образом не смогу так сделать
Почему не сможешь?
Используй второй вариант, в чем проблема?

#3
14:39, 6 авг 2019

oxotnik
> Вот рабочий код, работает под гцц
Мне нужно инициализировать поля структуры, а не класса. Но добавление  : CStruct{}, в список инициализации устраняет ошибки компиляции, спасибо!

#4
14:41, 6 авг 2019

v1c Такой вариант, предыдущий кривоват)

#include <iostream>

struct CStruct
{
    int i;
    float f;
};

class MyClass : public CStruct
{
public:
    constexpr MyClass(int inI, float inF) : CStruct{inI, inF}
    {
    }
};

constexpr MyClass obj(5, 10.f);

int main()
{
    std::cout << obj.i << ", " << obj.f << std::endl;
}
#5
14:43, 6 авг 2019

nes
> Используй второй вариант, в чем проблема?
Я написал почему это не вариант.

#6
14:44, 6 авг 2019

oxotnik
> Такой вариант, предыдущий кривоват)
Такой тоже работает:

class MyClass : public CStruct
{
public:
    constexpr MyClass(int inI, float inF): CStruct{}
    {
        i = inI;
        f = inF;
    }
};

Т. к. инициализация в compile-time то двойная инициализация накладных расходов не несёт, но она легче для восприятия. А если в структуре C array[] то через брэкеты уже не получится.

#7
14:54, 6 авг 2019

oxotnik
Сейчас попробовал здесь: http://cpp.sh/2ltsy
Компилится только если инициализация в брэкетах, тело конструктора не признаёт. Это GCC 4.9.2.
А вот GCC 5.4.0 уже компилирует и тело.
Короче в имплементации constexpr бардак, можно легко получить некомпилируемый код.

#8
14:57, 6 авг 2019

v1c
До с++14 тело конструктора должно быть пустое
Видимо  GCC 4.9.2 поддерживает только с++11

ПрограммированиеФорумОбщее

Тема в архиве.