Re[10]: std::variant для вложенного класса
От: sergii.p  
Дата: 05.12.25 16:03
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


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


BFE>
BFE>using value_type = float;

BFE>struct A
BFE>{
BFE>  struct B
BFE>  {
BFE>     value_type n = 0;
BFE>  };
BFE>  using value_type = int;
BFE>};
BFE>


только немного не так. Здесь value_type будет как раз float.

using value_t = float;

struct Outer {
    struct Inner {
        value_t i;
    };
    std::variant<Inner> v; // value_t = float, Inner - считается полным, конструктор создать можно, код компилируется
    using value_t = long long; // это переопределение уже никого не волнует, тип Inner готов
};


а вот как раз с дефолтной инициализацией компилятор не знает откуда взять определение

static constexpr int SuperDuperConst = 0;

struct Outer {
    struct Inner {
        int i = SuperDuperConst;
    };
    std::variant<Inner> v; // i должна быть равна 42, но мы ещё не добрались до определения SuperDuperConst и конструктор сгенерировать не можем - компиляция провалилась
    static constexpr int SuperDuperConst = 42;
};
Re[10]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 05.12.25 17:05
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>
BFE>using value_type = float;

BFE>struct A
BFE>{
BFE>  struct B
BFE>  {
BFE>     value_type n = 0;
BFE>  };
BFE>  using value_type = int;
BFE>};
BFE>


Не понял я что ты хотел сказать этим примером. По сути ты демонстрируешь следующее:

using value_type = float;

struct A
{
    static_assert(std::same_as<float, value_type>);
    using value_type = int;
    static_assert(std::same_as<int, value_type>);
};


Как это относится к обсуждаемой проблеме? Замени классы на пространства имен, получишь ровно то же самое.

А gcc на твой пример вообще плюнется ошибкой: "declaration of 'using A::value_type = int' changes meaning of 'value_type'".
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 05.12.2025 17:37 rg45 . Предыдущая версия . Еще …
Отредактировано 05.12.2025 17:28 rg45 . Предыдущая версия .
Отредактировано 05.12.2025 17:26 rg45 . Предыдущая версия .
Отредактировано 05.12.2025 17:24 rg45 . Предыдущая версия .
Отредактировано 05.12.2025 17:10 rg45 . Предыдущая версия .
Отредактировано 05.12.2025 17:07 rg45 . Предыдущая версия .
Re[11]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 05.12.25 17:55
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>
SP>static constexpr int SuperDuperConst = 0;

SP>struct Outer {
SP>    struct Inner {
SP>        int i = SuperDuperConst;
SP>    };
SP>    std::variant<Inner> v; // i должна быть равна 42, но мы ещё не добрались до определения SuperDuperConst и конструктор сгенерировать не можем - компиляция провалилась
SP>    static constexpr int SuperDuperConst = 42;
SP>};
SP>


А когда вместо SuperDuperConst используется литеральный ноль в качестве инициализатора, куда мы в этом случае ещё не добрались?
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 05.12.2025 18:19 rg45 . Предыдущая версия . Еще …
Отредактировано 05.12.2025 18:08 rg45 . Предыдущая версия .
Отредактировано 05.12.2025 18:01 rg45 . Предыдущая версия .
Отредактировано 05.12.2025 17:56 rg45 . Предыдущая версия .
Отредактировано 05.12.2025 17:55 rg45 . Предыдущая версия .
Re[11]: std::variant для вложенного класса
От: B0FEE664  
Дата: 05.12.25 18:17
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>только немного не так. Здесь value_type будет как раз float.

SP>а вот как раз с дефолтной инициализацией компилятор не знает откуда взять определение

То есть вы считаете, что поиск по имени константы и по имени типа является (и должен быть) различным? (как правильно я не разбирался)

Дело в том, что вот такой код:
using value_type = float;

struct O
{
  struct I
  {
     value_type n = 2.3;
  };
  using value_type = int;
};

int main() 
{
  O::I in;
  std::cout << in.n;
  return 0;
}


gcc не компилирует
error: declaration of 'using O::value_type = int' changes meaning of 'value_type' [-Wchanges-meaning]
39 | using value_type = int;
| ^~~~~~~~~~
<source>:37:6: note: used here to mean 'using value_type = float'
37 | value_type n = 2.3;
| ^~~~~~~~~~
<source>:31:7: note: declared here
31 | using value_type = float;

gcc здесь

а clang компилирует без предупреждений и выводит 2.3

clang здесь


код можно немного усложнить (с тем же эффектом: gcc: error, clanc: n — это float):
int f(int)
{
  return 0;
}

//template<class T = char> 
struct A
{
  int g() { return f(0); }           // здесь f - член класса       
  using value_Type = decltype(f(0)); // здесь f - внешняя функция?
  struct B
  {
     value_Type n = 1.1;
  } b;

   float f(int) { return 0;}
};


А здесь вообще волшебный результат:

constexpr float f(int)
{
  return 0;
}

struct A
{
  using value_Type = decltype(f(0));
  struct B
  {
     value_Type             n = f(0);
     static constexpr auto  m = f(0);
  } b;

   static constexpr  int f(int) { return 5;}
};

int main() 
{
  A a;
  std::cout << "n=" << a.b.n << '\n';
  std::cout << "m=" << a.b.m << '\n';

  return 0;
}


Program stdout
n=5
m=0
И каждый день — без права на ошибку...
Re: std::variant для вложенного класса
От: rg45 СССР  
Дата: 05.12.25 18:24
Оценка:
Здравствуйте, 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>здесь


По-моему, в стандарте явно не хватает разделения правил для инициализаторов, зависящих и не зависящих от контекста обрамляющего класса. Типа как существуют различные правила для выражений зависящих и не зависящих от параметров шаблона. Ну, провтыкали они этот момент, бывает.
--
Справедливость выше закона. А человечность выше справедливости.
Re[11]: std::variant для вложенного класса
От: B0FEE664  
Дата: 05.12.25 18:41
Оценка: :)
Здравствуйте, rg45, Вы писали:

  Скрытый текст
BFE>>
BFE>>using value_type = float;

BFE>>struct A
BFE>>{
BFE>>  struct B
BFE>>  {
BFE>>     value_type n = 0;
BFE>>  };
BFE>>  using value_type = int;
BFE>>};
BFE>>

R>Не понял я что ты хотел сказать этим примером.
Имя. Где искать имя?
Почему при декларации используется один порядок поиска имён, а при вызове — другой?
И каждый день — без права на ошибку...
Re[12]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 05.12.25 18:44
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>То есть вы считаете, что поиск по имени константы и по имени типа является (и должен быть) различным? (как правильно я не разбирался)


Там с этим unqualified name lookup сам чёрт лапы поломает. Но по факту выходит что да, правила разные.
--
Справедливость выше закона. А человечность выше справедливости.
Re[12]: std::variant для вложенного класса
От: rg45 СССР  
Дата: 05.12.25 18:45
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Имя. Где искать имя?

BFE>Почему при декларации используется один порядок поиска имён, а при вызове — другой?

Да вот, тоже сижу, втыкаю, пытаюсь разобраться. По факту получается, что правила разные для типов и для констант (объектов). А вот почему так...

Наиболее читабельно расписано вот здесь: https://en.cppreference.com/w/cpp/language/unqualified_lookup.html. Но то, что тут написано не очень согласуется с наблюдаемым поведением.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 05.12.2025 18:48 rg45 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.