Здравствуйте, 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;
};
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 используется литеральный ноль в качестве инициализатора, куда мы в этом случае ещё не добрались?
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, 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: 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;}
};
По-моему, в стандарте явно не хватает разделения правил для инициализаторов, зависящих и не зависящих от контекста обрамляющего класса. Типа как существуют различные правила для выражений зависящих и не зависящих от параметров шаблона. Ну, провтыкали они этот момент, бывает.
--
Справедливость выше закона. А человечность выше справедливости.
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>Не понял я что ты хотел сказать этим примером.
Имя. Где искать имя?
Почему при декларации используется один порядок поиска имён, а при вызове — другой?
Здравствуйте, B0FEE664, Вы писали:
BFE>То есть вы считаете, что поиск по имени константы и по имени типа является (и должен быть) различным? (как правильно я не разбирался)
Там с этим unqualified name lookup сам чёрт лапы поломает. Но по факту выходит что да, правила разные.
--
Справедливость выше закона. А человечность выше справедливости.