spamsink: (Default)
[personal profile] spamsink



Понадобилось мне давеча сделать нечто хитрое с помощью взаимно-рекурсивных классов.



Опуская непринципиальные для обсуждения детали, я написал нечто вроде

#include <iostream>
#include <vector>

struct Foo;

template <typename T> struct BarT { T foo1, foo2; }; // !!!
using Bar = BarT<Foo>; // !!!

struct Foo { std::vector<Bar> bar; };

// Демонстрация, что компилируется и работает
int main() {
Bar bar;
std::cout << sizeof(Foo) << ' ' << sizeof(Bar) << '\n';
}


А теперь внимание, вопрос: какого бы, собственно, рожна нас в XXI веке заставляют прыгать через обруч, вместо того, чтобы просто писать, взамен отмеченного !!!,

struct Bar { Foo foo1, foo2; };


Что мешает компилятору, при виде недоопределенных классов внутри определяемого класса, автоматически делать вид, что это был темплейт?



Date: 2024-04-24 09:01 pm (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Да это всё Строуструпная ментальность. Толпы людей зависли вот с этой всей ерундой в голове. "Как нам сделать хуже, чем в джаве, сишарпе и котлине? А вот так вот. Чтоб потом можно было показывать сложение матриц в виде просто операции +

Они как на другой планете живут. Ну или, точнее, в другом веке. В двадцатом.

scala> object Z {
     |   case class Pair(a1: Arr, a2: Arr)
     |   case class Arr(ps: List[Pair])
     | }
object Z

Тут нужен object Z, чтобы не давать ничему компилироваться, пока не закроем Z.

Date: 2024-04-24 09:13 pm (UTC)
vak: (Default)
From: [personal profile] vak
Совместимость с Си мешает. Пора уже от неё избавляться как-то. Не зря Страуструп недавно предложил концепцию профайлов.

https://github.com/BjarneStroustrup/profiles

Date: 2024-04-24 09:26 pm (UTC)
fatoff: What? (Default)
From: [personal profile] fatoff
Ну определил всё к моменту создания объекта, и удивляешься. Compile time evaluation is not run time evaluation. Как компилятору делать вид, что что-то тимплейт, но программист такого не имел в виду, тоже интересный момент. Все эти неявные преобразования создают много головной боли.

Date: 2024-04-24 09:43 pm (UTC)
fatoff: What? (Default)
From: [personal profile] fatoff
Да тут выше писали, почему ёжики не скрещиваются.

Примитивный пример понятен, а как компилятор будет "автоматически делать вид, что это был темплейт" не столь доступно. Разрешат они это. Дальше на вход поступят посложнее примеры. Неоднозначности применения тимплейта наступят.

Date: 2024-04-24 09:44 pm (UTC)
vak: (Default)
From: [personal profile] vak
Профили это обобщённый способ отказаться от наследования семантики Си, сохранив все черты Си++. В данном случае не требовать, чтобы в момент "создания" переменной её тип уже был определён. Он мог бы быть определён позже, как в других языках. Но Си такого не разрешает.

Можно представить себе специальный "профиль" Си++, где такое разрешается.

Date: 2024-04-24 10:00 pm (UTC)
ircicq: (Default)
From: [personal profile] ircicq
Конструкция struct Bar { Foo foo1, foo2; };

не защищена от опечаток.

а с template Foo повторено дважды.

Date: 2024-04-24 11:29 pm (UTC)
ircicq: (Default)
From: [personal profile] ircicq
Вы правы

Но что делать с?:
struct Bar { Foo *foo1; };

В Си это законная конструкция, например вынесенная в .h
и определений Foo может быть несколько в разных файлах

При шаблонизации будет порождено несколько классов Bar, которых линкер увидит под разными именами
(или под одним, но все равно неопределенность)

Edited Date: 2024-04-24 11:32 pm (UTC)

Date: 2024-04-25 05:58 am (UTC)
sab123: (Default)
From: [personal profile] sab123
Здесь, как я понимаю, случайно повезло, что размер vector не зависит от рамера Foo. А случись другая реализация vector, в которой он зависит (например, заодно резервирует там же место на первый десяток элементов) - и компилироваться не будет.

Profile

spamsink: (Default)
spamsink

February 2026

S M T W T F S
12345 67
8 91011 121314
15161718 192021
22 232425262728

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 24th, 2026 09:15 pm
Powered by Dreamwidth Studios