std::variant для вложенного класса
От: B0FEE664  
Дата: 03.12.25 20:05
Оценка: 11 (2) +1
Почему некоторые компиляторы это отказываются компилировать ?
#include <variant>

struct D
{
    struct FService
    {
        int  nFService_ = 0;
    };

    std::variant<FService> data_;
};

int main() 
{
D d;
return 0;
}


здесь
И каждый день — без права на ошибку...
Отредактировано 03.12.2025 20:06 B0FEE664 . Предыдущая версия .
Re: std::variant для вложенного класса
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 03.12.25 20:46
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Почему некоторые компиляторы это отказываются компилировать ?


Лучше соответствуют стандарту?


BFE>здесь


Там же вроде всё сказано?
Маньяк Робокряк колесит по городу
Re: std::variant для вложенного класса
От: kov_serg Россия  
Дата: 03.12.25 21:13
Оценка: -1
Здравствуйте, B0FEE664, Вы писали:

BFE>Почему некоторые компиляторы это отказываются компилировать ?

Реализация variant-ов кривая
Добавь туда пару типов std::variant<bool,FService> data_;
или пустой конструктор FService::FService() {}
и заработает
Re[2]: std::variant для вложенного класса
От: Doom100500 Израиль  
Дата: 04.12.25 06:42
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, B0FEE664, Вы писали:


BFE>>Почему некоторые компиляторы это отказываются компилировать ?


M>Лучше соответствуют стандарту?


Если убрать инициализацию (int nFService_ = 0; ) то компилируется.
Такая инициализация перестала быть стандартной?
Спасибо за внимание
Отредактировано 04.12.2025 6:43 Doom100500 . Предыдущая версия . Еще …
Отредактировано 04.12.2025 6:42 Doom100500 . Предыдущая версия .
Re: std::variant для вложенного класса
От: rg45 СССР  
Дата: 04.12.25 08:41
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Почему некоторые компиляторы это отказываются компилировать ?

BFE>
BFE>#include <variant>

BFE>struct D
BFE>{
BFE>    struct FService
BFE>    {
BFE>        int  nFService_ = 0;
BFE>    };

BFE>    std::variant<FService> data_;
BFE>};

BFE>int main() 
BFE>{
BFE>D d;
BFE>return 0;
BFE>}
BFE>


BFE>здесь


Я склоняюсь к тому, что это баг компилера. По идее, вложенность структур здесь не должна иметь никакого значения, а имеет.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 04.12.2025 8:42 rg45 . Предыдущая версия .
Re: std::variant для вложенного класса
От: rg45 СССР  
Дата: 04.12.25 09:37
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Почему некоторые компиляторы это отказываются компилировать ?


Я бы упростил постановку вопроса:

https://godbolt.org/z/P4do6chPo

#include <concepts>

struct D
{
    struct FService
    {
        int  nFService_ = 0;
    };

    static_assert(std::default_initializable<FService>); // error: static assertion failed
};


Какого Х?
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 04.12.2025 9:40 rg45 . Предыдущая версия .
Re[2]: std::variant для вложенного класса
От: Великий Мессия google
Дата: 04.12.25 10:50
Оценка:
в так в GCC тоже самое
сомневаюсь что два мажорный компиля синхронно не правы
Re[3]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 04.12.25 11:10
Оценка:
Здравствуйте, Великий Мессия, Вы писали:

ВМ>в так в GCC тоже самое

ВМ>сомневаюсь что два мажорный компиля синхронно не правы

Ну, в таком случае очень хотелось бы найти объяснение.

Выглядит очень странно: вынос структуры наружу или отказ от инициализации мембера устраняют ошибку. Кто-нибудь видит связь или логику? Я — нет.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: std::variant для вложенного класса
От: Великий Мессия google
Дата: 04.12.25 11:17
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Великий Мессия, Вы писали:


ВМ>>в так в GCC тоже самое

ВМ>>сомневаюсь что два мажорный компиля синхронно не правы

R>Ну, в таком случае очень хотелось бы найти объяснение.


R>Выглядит очень странно: вынос структуры наружу или отказ от инициализации мембера устраняют ошибку. Кто-нибудь видит связь или логику? Я — нет.


согласен
если бы не засветили здесь эту проблему
я бы сходил в issue кланга или на багзиллу gcc
задал вопросик

по issues кланга я похожих кейсов не нашел

так что, велком кто то зарепортите
и оставьте линк сюда
для мониторинга
Re[4]: std::variant для вложенного класса
От: sergii.p  
Дата: 04.12.25 14:17
Оценка: 10 (1) +2
Здравствуйте, rg45, Вы писали:

R>Ну, в таком случае очень хотелось бы найти объяснение.


R>Выглядит очень странно: вынос структуры наружу или отказ от инициализации мембера устраняют ошибку. Кто-нибудь видит связь или логику? Я — нет.


типа в этом случае вложенный класс считается неполным до завершения объявления внешнего

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88165

This declares a default constructor that might be defined implicitly by the compiler, **or** it might get deleted if the member definitions of D would make the implicit default constructor ill-formed. This is obviously very different from the case where you declare B(); There is no assertion that D is default constructible, the compiler has to deduce whether or not that's true. That depends on the default member initializer for D::i. The initializer (which is just '0' here) is a "complete class context" which means it is not processed until the class D is complete (this allows you to use other members, or e.g. sizeof(D) as the initializer).

A nested class like C::D is not complete until its enclosing class is complete. This means the initializer for C::D::i is compiled after C is complete. This means whether C::D is default constructible is not known until C is complete.

Re[5]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 04.12.25 14:38
Оценка:
Здравствуйте, sergii.p, Вы писали:

Имхо, самое важное в этом беспорядочном потоке сознания заключено вот в этом коротеньком утверждении:

A nested class like C::D is not complete until its enclosing class is complete.


Вот если бы ещё получить ссылку на соответствующий пункт стандарта, было бы совсем здорово.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: std::variant для вложенного класса
От: vopl Россия  
Дата: 04.12.25 14:56
Оценка: 16 (1) +1
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, sergii.p, Вы писали:


R>Имхо, самое важное в этом беспорядочном потоке сознания заключено вот в этом коротеньком утверждении:


R>

R>A nested class like C::D is not complete until its enclosing class is complete.


R>Вот если бы ещё получить ссылку на соответствующий пункт стандарта, было бы совсем здорово.


https://timsong-cpp.github.io/cppwp/class.mem.general#note-4
Re[7]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 04.12.25 15:07
Оценка:
Здравствуйте, vopl, Вы писали:

R>>Вот если бы ещё получить ссылку на соответствующий пункт стандарта, было бы совсем здорово.


V>https://timsong-cpp.github.io/cppwp/class.mem.general#note-4


А как тогда объяснить это:

https://godbolt.org/z/oPo3o5ME7

struct D
{
    struct FService
    {
        int  nFService_ = 0;
    };
    static_assert(sizeof(FService) != 0);  // OK
    static_assert(std::default_initializable<FService>); // static assertion failed
};


Выходит, класс "достаточно полный" для sizeof, но недостаточно полный для того, чтобы понять, что он default infitializable. Это как так?
--
Справедливость выше закона. А человечность выше справедливости.
Re[8]: std::variant для вложенного класса
От: vopl Россия  
Дата: 04.12.25 15:19
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, vopl, Вы писали:


R>>>Вот если бы ещё получить ссылку на соответствующий пункт стандарта, было бы совсем здорово.


V>>https://timsong-cpp.github.io/cppwp/class.mem.general#note-4


R>А как тогда объяснить это:


R>https://godbolt.org/z/oPo3o5ME7


R>
R>struct D
R>{
R>    struct FService
R>    {
R>        int  nFService_ = 0;
R>    };
R>    static_assert(sizeof(FService) != 0);  // OK
// не является complete-class context так как не является ни одним из перечисленных вариантов в 10.1 - 10.6 отсюда https://timsong-cpp.github.io/cppwp/class.mem.general#10

R>    static_assert(std::default_initializable<FService>); // static assertion failed
// тут complete-class context это инициализирующее выражение "0" для FService::nFService_ (https://timsong-cpp.github.io/cppwp/class.mem.general#10.6), размещенное "within the member-specification", коим является static_assert (https://timsong-cpp.github.io/cppwp/class.mem.general#nt:member-declaration)
// этот complete-class context провоцирует дефолтный конструктор FService к удалению, тест default_initializable проваливается, получаем ложь и провал static_assert
R>};
R>


R>Выходит, класс "достаточно полный" для sizeof, но недостаточно полный для того, чтобы понять, что он default infitializable. Это как так?
Re[9]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 04.12.25 15:23
Оценка:
Здравствуйте, vopl, Вы писали:

R>>
R>>struct D
R>>{
R>>    struct FService
R>>    {
R>>        int  nFService_ = 0;
R>>    };
R>>    static_assert(sizeof(FService) != 0);  // OK
V>// не является complete-class context так как не является ни одним из перечисленных вариантов в 10.1 - 10.6 отсюда https://timsong-cpp.github.io/cppwp/class.mem.general#10

R>>    static_assert(std::default_initializable<FService>); // static assertion failed
V>// тут complete-class context это инициализирующее выражение "0" для FService::nFService_ (https://timsong-cpp.github.io/cppwp/class.mem.general#10.6), размещенное "within the member-specification", коим является static_assert (https://timsong-cpp.github.io/cppwp/class.mem.general#nt:member-declaration)
V>// этот complete-class context провоцирует дефолтный конструктор FService к удалению, тест default_initializable проваливается, получаем ложь и провал static_assert
R>>};
R>>


Примерно понял, спасибо. Почитаю ещё документ повнимательнее.

PS. Хотя логика этих зависимостей мне не очень понятна. Получается, что в обрамляющем классе можно написать нечто такое, отчего вложенный класс не сможет быть default initializable. В противном случае зачем эти сложности.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 04.12.2025 15:30 rg45 . Предыдущая версия . Еще …
Отредактировано 04.12.2025 15:29 rg45 . Предыдущая версия .
Re[6]: std::variant для вложенного класса
От: sergii.p  
Дата: 04.12.25 15:48
Оценка: 16 (1) +1
Здравствуйте, rg45, Вы писали:

R>Вот если бы ещё получить ссылку на соответствующий пункт стандарта, было бы совсем здорово.


[class.mem.general]

[Note 4 : A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested
class is defined within the member-specification of the enclosing class. — end note]
7 A class is considered a completely-defined object type (6.8) (or complete type) at the closing } of the
class-specifier. The class is regarded as complete within its complete-class contexts; otherwise it is regarded
as incomplete within its own class member-specification.

Re[7]: std::variant для вложенного класса
От: Великий Мессия google
Дата: 04.12.25 15:55
Оценка: 24 (2)
Здравствуйте, sergii.p, Вы писали:

SP>Здравствуйте, rg45, Вы писали:


R>>Вот если бы ещё получить ссылку на соответствующий пункт стандарта, было бы совсем здорово.


SP>[class.mem.general]


SP>

SP>[Note 4 : A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested
SP>class is defined within the member-specification of the enclosing class. — end note]
SP>7 A class is considered a completely-defined object type (6.8) (or complete type) at the closing } of the
SP>class-specifier. The class is regarded as complete within its complete-class contexts; otherwise it is regarded
SP>as incomplete within its own class member-specification.


о! нашел таки на llvm
работают над исправлением как я понял,но вяло

https://github.com/llvm/llvm-project/issues/60321
Re[8]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 05.12.25 10:28
Оценка: :)
Здравствуйте, Великий Мессия, Вы писали:

ВМ>о! нашел таки на llvm

ВМ>работают над исправлением как я понял,но вяло

ВМ>https://github.com/llvm/llvm-project/issues/60321


Ну вот, а мне тут про какие-то контексты лапшу на уши навешивают
--
Справедливость выше закона. А человечность выше справедливости.
Re[9]: std::variant для вложенного класса
От: sergii.p  
Дата: 05.12.25 10:51
Оценка: :))
Здравствуйте, rg45, Вы писали:

ВМ>>https://github.com/llvm/llvm-project/issues/60321


R>Ну вот, а мне тут про какие-то контексты лапшу на уши навешивают


ну так и в этом тикете такая же лапша. "Классы, контексты какие-то. Взять всё, и починить!". А меж тем тикету 3 года уже. Думаю разработчики сами плохо понимают аргументацию в стандарте, но это хорошая отмазка не чинить
Re[9]: std::variant для вложенного класса
От: B0FEE664  
Дата: 05.12.25 15:27
Оценка: 12 (1)
Здравствуйте, rg45, Вы писали:

R>Ну вот, а мне тут про какие-то контексты лапшу на уши навешивают


using value_type = float;

struct A
{
  struct B
  {
     value_type n = 0;
  };
  using value_type = int;
};
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.