Size: a a a

2020 June 26

VS

Vlad Serebrennikov in pro.cxx
у меня нет тут серьезных аргументов, но и ваши меня не убеждают
источник

VS

Vlad Serebrennikov in pro.cxx
и как трактовать то предложение из unary.op.1 для мне все еще вопрос
источник

CD

Constantine Drozdov in pro.cxx
Так мой изначальный тезис - сделать именно разыменование прямо обязывающим. Для T * p вычисление *p UB если (см. правила когда можно читать объект)
источник

CD

Constantine Drozdov in pro.cxx
Иначе получится, что мы стандартизировали this как указатель, эквивалентный ссылке, и при этом заубали случай (4)
источник

AD

Andrey Davydov in pro.cxx
Vlad Serebrennikov
Andrey здравствуйте. В очередной раз хочу поднять тему нулевого указателя.
Примеры кода, поведение которых хотелось бы у вас прояснить (по возможности со ссылками на стандарт):
A *p{nullptr};
*p; // 1
std::cout << (*p, 5); // 2
A a{*p}; // 3
p->non_static_mem_fn(); // 4
p->static_mem_fn(); // 5
Я, честно говоря, не понимаю, почему вы решил обратиться ко мне, я не language lawyer и нахожу в этих разговорах про разыменование nullptr смысла не больше, чем в подсчете ангелов на кончике острия.
Могу подсказать куда обратиться: slack cpplang, channel #standardese. У него даже description "Is this UB?", там такое любят.
источник

NP

Nikita Provotorov in pro.cxx
Александр Караев
Хочу перейти с виртуального интерфейса на статический. Если упрощенно, то вместо:

struct I { virtual void foo() { /* nothing */ } };
struct A : I { void foo() final { /* impl */ } };
struct B : I { /* no foo */ };


Иметь

struct A { void foo() { /* impl */ } };
struct B { /* no foo */ };


Я могу отличить A от B, проверив статически наличие void foo(), но есть нюанс - нет аналога final/override. То есть, если я ошибусь в сигнатуре функции или опечатаюсь в названии, компилятор меня не поправит. Есть способ решить эту проблему? Я думал в сторону каких-нибудь варнингов, которые будут реагировать на неиспользуемый метод. Компилятор - gcc.
в голову пришла идея - завести в базовом классе в приватной части структуры-теги, и делать каждый такой тег доступным для использования только в одном методе наследника. тогда если происходит попытка переопределения метода с другим именем или сигнатурой то будет ошибка компиляции.
потребует CRTP и я не уверен что "делать каждый такой тег доступным для использования только в одном методе наследника" вообще реализуемо, возможно у вас получится развить идею
источник

CD

Constantine Drozdov in pro.cxx
Andrey Davydov
Я, честно говоря, не понимаю, почему вы решил обратиться ко мне, я не language lawyer и нахожу в этих разговорах про разыменование nullptr смысла не больше, чем в подсчете ангелов на кончике острия.
Могу подсказать куда обратиться: slack cpplang, channel #standardese. У него даже description "Is this UB?", там такое любят.
А есть идеи, какие могут быть проблемы, если прямо с формулировкой "разыменование указателя равносильно чтению данных по указателю" заубать всё это?
источник

АК

Александр Караев... in pro.cxx
Nikita Provotorov
в голову пришла идея - завести в базовом классе в приватной части структуры-теги, и делать каждый такой тег доступным для использования только в одном методе наследника. тогда если происходит попытка переопределения метода с другим именем или сигнатурой то будет ошибка компиляции.
потребует CRTP и я не уверен что "делать каждый такой тег доступным для использования только в одном методе наследника" вообще реализуемо, возможно у вас получится развить идею
мысль с friend и тегами отличная, попробую развить, спасибо
источник

AD

Andrey Davydov in pro.cxx
Constantine Drozdov
А есть идеи, какие могут быть проблемы, если прямо с формулировкой "разыменование указателя равносильно чтению данных по указателю" заубать всё это?
Такой case:
char a[10];
char *b = &a[10];

было бы нелогично иметь тут UB.
источник

VS

Vlad Serebrennikov in pro.cxx
Andrey Davydov
Я, честно говоря, не понимаю, почему вы решил обратиться ко мне, я не language lawyer и нахожу в этих разговорах про разыменование nullptr смысла не больше, чем в подсчете ангелов на кончике острия.
Могу подсказать куда обратиться: slack cpplang, channel #standardese. У него даже description "Is this UB?", там такое любят.
спасибо за наводку. этот канал я как-то упустил.
там даже нашлось небольшое обсуждение этого же вопроса, но ничего нового там не прозвучало
источник

ПК

Побитый Кирпич... in pro.cxx
Александр Караев
Хочу перейти с виртуального интерфейса на статический. Если упрощенно, то вместо:

struct I { virtual void foo() { /* nothing */ } };
struct A : I { void foo() final { /* impl */ } };
struct B : I { /* no foo */ };


Иметь

struct A { void foo() { /* impl */ } };
struct B { /* no foo */ };


Я могу отличить A от B, проверив статически наличие void foo(), но есть нюанс - нет аналога final/override. То есть, если я ошибусь в сигнатуре функции или опечатаюсь в названии, компилятор меня не поправит. Есть способ решить эту проблему? Я думал в сторону каких-нибудь варнингов, которые будут реагировать на неиспользуемый метод. Компилятор - gcc.
Полиморфизм то где? Если у тебя полиморфизм на шаблонах (статический), то там всё просто. Если при интанцировании и использовании не будет такого метода, то не скомпилируется.
источник

ПК

Побитый Кирпич... in pro.cxx
Получается аналог override (именно в части проверок) уже есть неявно (или в виде концептов, как угодно), а final не нужен, потому что нет наследования
источник

NP

Nikita Provotorov in pro.cxx
Побитый Кирпич
Получается аналог override (именно в части проверок) уже есть неявно (или в виде концептов, как угодно), а final не нужен, потому что нет наследования
если хочется иметь дефолтную имплементацию то нет оверрайда
источник

ПК

Побитый Кирпич... in pro.cxx
Nikita Provotorov
если хочется иметь дефолтную имплементацию то нет оверрайда
Дефолтная имплементация это когда ты в шаблонной функции проверяешь есть ли у объекта нужный метод, и если его нет, то вызываешь свою "дефолтную функцию". Вроде это ниблоиды как раз и есть (см. swap)
источник

CD

Constantine Drozdov in pro.cxx
Andrey Davydov
Такой case:
char a[10];
char *b = &a[10];

было бы нелогично иметь тут UB.
Понял
источник

NP

Nikita Provotorov in pro.cxx
Побитый Кирпич
Дефолтная имплементация это когда ты в шаблонной функции проверяешь есть ли у объекта нужный метод, и если его нет, то вызываешь свою "дефолтную функцию". Вроде это ниблоиды как раз и есть (см. swap)
ниблоиды это же про adl не?
а по поводу переопределения, товарищ хочет аналог оверрайда который будет в компиль тайме стрелять если сигнатура неправильная или имя, так что простой поиск метода в наследнике не пойдет
источник

АК

Александр Караев... in pro.cxx
Побитый Кирпич
Полиморфизм то где? Если у тебя полиморфизм на шаблонах (статический), то там всё просто. Если при интанцировании и использовании не будет такого метода, то не скомпилируется.
Полиморфизм на type erasure. Представь концепт
template <class T> concept HasFoo = requires (T& t) { t.foo(); }
У меня есть много типов, которые я единообразно обрабатываю. Для типов T, удовлетворяющих концепту, я вызываю foo(). Иначе - нет операции. Если я опечатаюсь в сигнатуре или названии, класс не сможет это определить и просто выкинет вызов "неправильной" foo
источник

ПК

Побитый Кирпич... in pro.cxx
Nikita Provotorov
ниблоиды это же про adl не?
а по поводу переопределения, товарищ хочет аналог оверрайда который будет в компиль тайме стрелять если сигнатура неправильная или имя, так что простой поиск метода в наследнике не пойдет
Какой наследник? Нет у нас наследования. Есть
template <typename SomeConcept>
void foo(SomeConcept some) {
 some.bar();
}

Работает со всем у чего есть bar
источник

CD

Constantine Drozdov in pro.cxx
Александр Караев
Хочу перейти с виртуального интерфейса на статический. Если упрощенно, то вместо:

struct I { virtual void foo() { /* nothing */ } };
struct A : I { void foo() final { /* impl */ } };
struct B : I { /* no foo */ };


Иметь

struct A { void foo() { /* impl */ } };
struct B { /* no foo */ };


Я могу отличить A от B, проверив статически наличие void foo(), но есть нюанс - нет аналога final/override. То есть, если я ошибусь в сигнатуре функции или опечатаюсь в названии, компилятор меня не поправит. Есть способ решить эту проблему? Я думал в сторону каких-нибудь варнингов, которые будут реагировать на неиспользуемый метод. Компилятор - gcc.
С точки зрения статического полиморфизма произошедшее не является ошибкой, но факт "наследования" ты просто указываешь через static_assert
источник

ПК

Побитый Кирпич... in pro.cxx
Александр Караев
Полиморфизм на type erasure. Представь концепт
template <class T> concept HasFoo = requires (T& t) { t.foo(); }
У меня есть много типов, которые я единообразно обрабатываю. Для типов T, удовлетворяющих концепту, я вызываю foo(). Иначе - нет операции. Если я опечатаюсь в сигнатуре или названии, класс не сможет это определить и просто выкинет вызов "неправильной" foo
Дак это не статический полиморфизм уже
источник