Другими словами: может ли класс Foo пройти этот тест во время компиляции?
void prove_the_point() {
Foo foo1{};
const Foo foo2{};
static_assert(sizeof(foo1) != sizeof(foo2));
}
Я унаследовал большой проект в области науки о данных. Чтобы облегчить рассуждения в коде, я начал обеспечивать соблюдение константной корректности. Есть объекты, указатели на объекты, которые мне чаще всего приходилось заменять наshared_ptr, векторы и неизбежно векторы умных указателей.
Теперь вы можете видеть, к чему это идет: обеспечить константную корректность вектораshared_ptr, возможно, невозможно, потому что const не распространяется без изменения семантики API (например, путем предоставления итераторов вместо векторов указателей).
В комментариях к Как я могу распространить const при возврате std::vector<int*> из метода const?, @Voo предположил, что reinterpret_cast нельзя использовать, поскольку нет гарантии, что расположение памяти для T и const T одинаково. Если это правда, то это означает, что распространение const никогда не будет работать, потому что типы Foo и const Foo в принципе могут быть совершенно не связаны.
Это заставило меня задуматься, можно ли это доказать. Я уже знаю, что могу специализировать методы на постоянстве типа, но могу ли я специализировать весь класс, чтобы у меня были разные члены данных для T и const T?
Зачем отмечать одновременно C++20 и C++26? Какую версию вы используете?
Я не понимаю, как приведенный пример иллюстрирует вопрос, он не использует никакого шаблона. Вы имели в виду Foo<T> против Foo<const T>?
Это совсем не то, о чем вы спрашивали, но ваша функция возможна, если Foo является шаблоном класса: godbolt.org/z/K7nExGcGq
@Артьер, очень хитрый :O
@TedLyngmo моя база кода совместима с C++20, но мне интересна проблема в принципе, поэтому я добавил также самую последнюю версию.
@AdamRyczkowski C++23 еще даже не выпущен, а работа над C++26 только началась. Чтобы сузить круг задач, обычно лучше придерживаться той версии, с которой вы на самом деле компилируете.





Могу ли я специализировать шаблон класса на постоянстве типа?
Нет. const не является частью специализации шаблона.
Может ли класс Foo пройти этот тест времени компиляции?
Нет. sizeof игнорирует const. const не влияет на свойства типа.
обеспечить константную корректность вектораshared_ptr, возможно, невозможно, потому что
В самом const есть свойство shared_ptr, которого можно добиться, передав std::vector<std::shared_ptr<T>> как std::span<const std::shared_ptr<T>>.
Также существует свойство const в T, которое должно быть независимым от const в shared_ptr. Распространение shared_ptr с помощью const по всему вектору немного сложнее, в зависимости от того, что именно вы хотите сделать. Возникает вопрос, почему вам нужно передавать std::vector<std::shared_ptr<T>> таким образом, чтобы доступ к элементам T был const. Возможно, передача std::vector<const T*>, созданного на основе исходного вектора, более уместна, если право собственности не перешло.
В комментариях к статье «Как я могу распространять const при возврате std::vector<int*> из метода const?» @Voo предположил, что reinterpret_cast нельзя использовать, поскольку нет гарантии, что расположение памяти для T и const T является такой же. Если это правда, то это означает, что распространение const никогда не будет работать, потому что типы Foo и const Foo в принципе могут быть совершенно не связаны.
То, что reinterpret_cast имеет неопределенное поведение, не имеет никакого отношения к тому, связаны ли T и const T или имеют одинаковую компоновку. reinterpret_castмежду несвязанными типами почти во всех случаях происходит UB, независимо от макета. Макет вообще не определяет, допустимо ли такое приведение. Два типа, являющиеся специализациями одного и того же шаблона, не считаются «родственными». Кроме того, даже если T и const T абсолютно одинаковы во всех отношениях, нет никакой гарантии, что std::vector<const T> и std::vector<T> имеют одинаковый макет и свойства.
Вы правы, говоря, что const не меняет структуру памяти T, что и измеряет sizeof. Но это не значит, что const не влияет на свойства T ; это все еще влияет на то, как можно использовать T
@AbhishekShivakumar В некотором роде зависит от интерпретации «свойств типа». Дело в том, что, за исключением того, что T является отличным от const T типом, оба типа имеют общие свойства. Единственное отличие состоит в том, что объект последнего типа имеет ограничения на модификацию и что выражение типа const ведет себя по-разному при разрешении перегрузки и в том, что с ним можно использовать встроенные выражения.
«поскольку нет никакой гарантии, что расположение памяти для
Tиconst Tодинаково» Полагаю, ваша ссылка этого не говорит? Там написано, чтоvector<T>иvector<const T>могут быть разными, а вы это не то, что говорите.