Это несколько странный вопрос. Мои цели - понять решение о языковом дизайне и определить возможности отражения в C++.
Почему комитет по языку C++ не пошел на реализацию отражения на языке? Слишком сложно рефлексировать на языке, который не работает на виртуальной машине (например, java)?
Если бы нужно было реализовать отражение для C++, какие были бы проблемы?
Я полагаю, что использование отражения хорошо известно: редакторы могут быть легче написаны, программный код будет меньше, могут быть созданы макеты для модульных тестов и так далее. Но было бы здорово, если бы вы также могли прокомментировать использование отражения.





Отражение требует, чтобы некоторые метаданные о типах были где-то храниться, чтобы их можно было запросить. Поскольку C++ компилируется в собственный машинный код и претерпевает серьезные изменения из-за оптимизации, высокоуровневое представление приложения в значительной степени теряется в процессе компиляции, следовательно, невозможно будет запросить их во время выполнения. Java и .NET используют представление очень высокого уровня в двоичном коде виртуальных машин, что делает возможным такой уровень отражения. Однако в некоторых реализациях C++ есть нечто, называемое информацией о типе времени выполнения (RTTI), которое можно рассматривать как урезанную версию отражения.
Но не все реализации C++ являются стандартными. Я видел реализации, которые не поддерживают RTTI.
И большинство реализаций, которые поддерживают RTTI, также поддерживают отключение с помощью параметров компилятора.
Отражение может быть и было реализовано в C++ раньше.
Это не встроенная функция C++, потому что у нее высокая стоимость (память и скорость), которые не должны устанавливаться языком по умолчанию - язык ориентирован на «максимальную производительность по умолчанию».
Так как вы не должны платить за то, что вам не нужно, и, как вы сами говорите, в редакторах этого нужно больше, чем в других приложениях, то это должно быть реализовано только там, где вам это нужно, а не «принудительно» для всего кода ( вам не нужно отражать все данные, с которыми вы будете работать в редакторе или другом аналогичном приложении).
и вы не отправляете символы, потому что это позволит вашим клиентам / конкурентам взглянуть на ваш код ... это часто считается плохим.
Вы правы, я даже не задумывался о проблеме с выставлением кода :)
Причина, по которой C++ не имеет отражения, заключается в том, что это потребовало бы от компиляторов добавления символьной информации в объектные файлы, например, какие члены имеет тип класса, информацию о членах, о функциях и всем остальном. По сути, это сделает включаемые файлы бесполезными, поскольку информация, отправляемая объявлениями, затем будет считана из этих объектных файлов (а затем модулей). В C++ определение типа может встречаться в программе несколько раз за счет включения соответствующих заголовков (при условии, что все эти определения одинаковы), поэтому нужно будет решить, куда поместить информацию об этом типе, так же как назвать один сложность здесь. Еще одна сильная сторона - агрессивная оптимизация, выполняемая компилятором C++, который может оптимизировать десятки экземпляров шаблонов классов. Это возможно, но, поскольку C++ совместим с C, это стало бы неудобной комбинацией.
Я не понимаю, чем сильная сторона агрессивной оптимизации компилятора. Вы можете уточнить? Если компоновщик может удалить повторяющиеся определения встроенных функций, в чем проблема с дублированием информации об отражении? Разве символьная информация не добавляется в объектные файлы для отладчиков?
Проблема в том, что ваша информация об отражении может быть недействительной. Если компилятор удаляет 80% определений вашего класса, что скажут ваши метаданные отражения? В C# и Java язык гарантирует, что если вы определите класс, он останется определенным. C++ позволяет компилятору оптимизировать его.
@Rob, оптимизации - это еще один момент, не связанный с усложнением нескольких классов. См. Комментарий @jalf (и его ответ), чтобы узнать, что я имел в виду.
Если я создаю экземпляр reflection <T>, не выбрасывайте никакую информацию T. Это не кажется неразрешимой проблемой.
Если вы действительно хотите понять проектные решения, связанные с C++, найдите копию Справочное руководство по C++ с аннотациями Эллиса и Страуструпа. Он НЕ соответствует последнему стандарту, но он проходит через исходный стандарт и объясняет, как все работает и как часто это происходит.
Также Дизайн и развитие C++ от Страуструпа
Отражение для языков, в которых оно есть, касается того, какую часть исходного кода компилятор готов оставить в вашем объектном коде, чтобы включить отражение, и сколько механизмов анализа доступно для интерпретации этой отраженной информации. Если компилятор не хранит весь исходный код, рефлексия будет ограничена в своей способности анализировать доступные факты об исходном коде.
Компилятор C++ ничего не хранит (ну, игнорируя RTTI), поэтому вы не получите отражения в языка. (Компиляторы Java и C# хранят только имена классов, методов и возвращаемые типы, поэтому вы получаете немного данных отражения, но не можете проверять выражения или структуру программы, а это означает, что даже в этих языках с поддержкой отражения информация, которую вы можете получить, довольно скудна, и, следовательно, вы действительно не можете провести большой анализ).
Но вы можете изменить язык вне и получить полную возможность отражения. Ответ на другое обсуждение переполнения стека на отражение в C обсуждает это.
Я считаю, что отражение в C++ крайне важно, если C++ будет использоваться в качестве языка для доступа к базам данных, обработки веб-сеансов / http и разработки графического интерфейса. Отсутствие отражения предотвращает использование ORM (таких как Hibernate или LINQ), синтаксических анализаторов XML и JSON, которые создают экземпляры классов, сериализации данных и многих других вещей (где изначально для создания экземпляра класса должны использоваться данные без типа).
Можно использовать переключатель времени компиляции, доступный разработчику программного обеспечения во время процесса сборки. чтобы устранить эту озабоченность «вы платите за то, что используете».
Я разработчик прошивки не нуждается в отражении для чтения данных из последовательного порта - тогда лучше не использовать коммутатор. Но как разработчик базы данных, который хочет продолжать использовать C++, я постоянно использую ужасный, сложный в обслуживании код, который отображает данные между элементами данных и конструкциями базы данных.
Ни сериализация Boost, ни другой механизм на самом деле не решают проблему отражения - это должно выполняться компилятором - и как только это будет сделано, C++ снова будет изучаться в школах и использоваться в программном обеспечении, которое имеет дело с обработкой данных.
Для меня это проблема №1 (а примитивы с простыми потоками - это проблема №2).
Кто сказал, что C++ является можно использовать в качестве языка для доступа к БД, управления веб-сессиями или графического интерфейса разработчика? Есть много гораздо лучших языков, которые можно использовать для такого рода вещей. И переключатель времени компиляции не решит проблему. Обычно решение о включении или отключении отражения не принимается отдельно для каждого файла. Это могло бы сработать, если бы его можно было включить для отдельных типов. Если программист может указать с помощью атрибута или подобного при определении типа, должны ли создаваться метаданные отражения для него. Но глобальный переключатель? Вы испортили бы 90% информации, чтобы сделать ее проще на 10%.
Затем, если мне нужна кроссплатформенная программа с доступом к графическому интерфейсу, что мне следует использовать? Несгибаемый java-качели? Окна только C#? Но правда следует сказать, и правда в том, что есть много программ, которые скомпилированы в исполняемый код и предлагают графический интерфейс и доступ к базам данных, поэтому они должны использовать некоторую базу данных и поддержку графического интерфейса ... И это не так. t с помощью QT. (он должен был называться MT (набор инструментов для монстров))
@ Coyote21: C# уже много лет не предназначен только для Windows. (Хотя я не фанат Mono, он работает достаточно хорошо для большинства вещей.) Swing - не единственный инструментарий GUI для Java. По правде говоря, любой из них будет лучшим выбором, если вы хотите кроссплатформенность. С ++ почти всегда будет иметь части, специфичные для платформы, здесь или там, если вы делаете что-то нетривиальное.
Нет причин, по которым вам нужна рефлексия для ORM. Вы можете добиться всего этого с помощью шаблонов. Существует множество фреймворков, которые предоставляют ORM для C++.
Как это на самом деле отвечает на вопрос?
Если бы C++ мог иметь:
constconstЭтого было бы достаточно, чтобы создать очень простые в использовании библиотеки, необходимые для безтиповой обработки данных, которая так распространена в современных веб-приложениях и приложениях баз данных. (все ормы, механизмы обмена сообщениями, парсеры xml / json, сериализация данных и т. д.).
Например, основная информация, поддерживаемая макросом Q_PROPERTY (часть Qt Framework)
http://qt.nokia.com/doc/4.5/properties.html расширен, чтобы охватить методы класса и e) - было бы чрезвычайно полезно для C++ и для сообщества разработчиков программного обеспечения в целом.
Конечно, отражение, о котором я говорю, не охватывает семантическое значение или более сложные вопросы (например, номера строк исходного кода комментариев, анализ потока данных и т. д.), Но я также не думаю, что они должны быть частью языкового стандарта.
@Vlad: Да, если добавить в язык функции, поддерживающие отражение, вы получите отражение в языке. Это может произойти только в том случае, если языковой комитет примет это постановление, а я думаю, что они этого не сделали с 2011 года, и я сомневаюсь, что до 2020 года нашей эры будет выпущен еще один стандарт C++. Итак, хорошая мысль. Между тем, если вы хотите добиться прогресса, вам, вероятно, придется выйти за рамки C++.
По словам Алистера Кокберна, подтипирование не может быть гарантировано в рефлексивной среде.
Рефлексия более актуальна для систем скрытой печати. В C++ вы знаете, какой у вас тип, и знаете, что с ним делать.
В более общем смысле, возможность проверить наличие функции, которая не существует, без введения неопределенного поведения делает возможным, что добавление этой функции в более позднюю версию класса изменит четко определенное поведение уже существующих программ и следовательно, невозможно гарантировать, что добавление этой функции ничего не «сломает».
Все языки не должны пытаться включать все функции любого другого языка.
C++ - это, по сути, очень и очень сложный ассемблер макросов. Это НЕ (в традиционном смысле) язык высокого уровня, такой как C#, Java, Objective-C, Smalltalk и т. д.
Хорошо иметь разные инструменты для разных работ. Если у нас есть только молотки, все будет похоже на гвозди и т. д. Наличие языков сценариев полезно для некоторых работ, а рефлексивные OO-языки (Java, Obj-C, C#) полезны для другого класса работ, и супер -эффективные простые языки, близкие к машинным, полезны для еще одного класса задач (C++, C, Assembler).
C++ делает потрясающую работу по расширению технологии Assembler до невероятных уровней управления сложностью и абстракций, чтобы сделать программирование более масштабных и сложных задач гораздо более доступным для людей. Но это не обязательно язык, который лучше всего подходит для тех, кто подходит к своей проблеме с точки зрения строго высокого уровня (Lisp, Smalltalk, Java, C#). Если вам нужен язык с этими функциями, чтобы наилучшим образом реализовать решение ваших проблем, поблагодарите тех, кто создал такие языки для всех нас!
Но C++ предназначен для тех, кому по каким-либо причинам необходимо иметь сильную корреляцию между их кодом и работой базовой машины. Будь то эффективность, программирование драйверов устройств, взаимодействие с низкоуровневыми службами ОС или что-то еще, C++ лучше подходит для этих задач.
C#, Java, Objective-C - все требуют гораздо более обширной и богатой системы времени выполнения для поддержки их выполнения. Эта среда выполнения должна быть доставлена в рассматриваемую систему - предварительно установлена для поддержки работы вашего программного обеспечения. И этот уровень необходимо поддерживать для различных целевых систем, настраивая НЕКОТОРЫЙ ДРУГОЙ ЯЗЫК, чтобы он работал на этой платформе. И этот промежуточный уровень - этот адаптивный уровень между ОС хоста и вашим кодом - среда выполнения почти всегда написана на таком языке, как C или C++, где эффективность - номер 1, где предсказуемо точное взаимодействие между программным обеспечением и оборудованием может быть хорошо понимал и манипулировал с максимальной выгодой.
Мне нравится Smalltalk, Objective-C и богатая среда выполнения с отражением, метаданными, сборкой мусора и т. д. Чтобы воспользоваться этими возможностями, можно написать потрясающий код! Но это просто более высокий уровень в стеке, уровень, который должен лежать на более низких уровнях, который, в конечном итоге, должен лежать на ОС и оборудовании. И нам всегда будет нужен язык, который лучше всего подходит для создания этого слоя: C++ / C / Assembler.
Приложение: C++ 11/14 продолжает расширять возможности C++ для поддержки абстракций и систем более высокого уровня. Распределение потоков, синхронизация, точные модели памяти, более точные определения абстрактных машин позволяют разработчикам C++ достигать многих высокоуровневых абстракций, которые некоторые из этих языков высокого уровня использовали для монопольной области, продолжая при этом обеспечивать близкие к - металлические характеристики и отличная предсказуемость (т.е. минимальное время работы подсистем). Возможно, в будущей версии C++ для тех, кто этого хочет, средства отражения будут выборочно включены - или, возможно, библиотека будет предоставлять такие службы времени выполнения (может быть, они есть сейчас или они только начинаются?).
Ваше мнение о среде выполнения языка, который должен быть скомпилирован на другом языке, неверен в случае Objective-C, поскольку его среда выполнения написана на C (который Objective-C является надмножеством).
Это различие без разницы. Какая разница, если в конечном итоге подсистема времени выполнения, которую использует Objective-C, на самом деле написана не на Objective-C, а, скорее, на C?
Objective-C является C, и в этом суть. Любая программа на C является допустимой для Objective-C, поэтому ее система времени выполнения фактически компилируется на ее собственном языке.
Нет, вы не можете написать программу Objective-C, которая компилируется с помощью компилятора C. Это разные языки. Вы не можете создавать объекты Obj-C, вы не можете использовать какие-либо службы отражения времени выполнения в C и т. д. Просто потому, что Objective-C расширяет C, не делает их одним языком и не устраняет необходимость в подсистеме времени выполнения для управления временем жизни объекта. и система типовых запросов, среди других функций Objective-C.
Мне жаль; но если вы правильно свяжете его, вы можете скомпилировать программу objective-c на C, на самом деле я сделал это здесь: stackoverflow.com/a/10290255/427309. Все ваше заявление выше ложно. Среда выполнения полностью доступна через C, и это одна из вещей, которая делает ее таким мощным динамическим языком.
Право ... через C. C. Требуется. Для Objective-C существует среда выполнения. Эта среда выполнения управляет отражением типов, передачей сообщений, объектами классов, управлением памятью и т. д. Я не уверен, что вы зацикливаетесь или считаете неправильным. Без среды выполнения Objective-C не существовал бы. В C++ нет среды выполнения (нет отражения динамического типа, нет подсистемы управления памятью, нет динамической привязки вызовов за пределами v-таблиц). Это сильное различие, и это чистая правда.
Незначительный педантичный момент: у C++ и C также есть система времени выполнения. Тот факт, что вы можете встроить среду выполнения в двоичный файл или что они обычно меньше, чем CLR / JVM, ортогонален их существованию (привет, msvcrtXXX.dll!). Вы должны отказаться от таких вещей, как malloc, чтобы получить настоящие бинарные файлы с голыми костями без времени выполнения (например: см. Поддержку Rust libcore для написания загрузчиков и ядер, где вы предоставляете пару базовых функций начальной загрузки, таких как malloc, или просто полностью избегаете выделения кучи)
Педантическое исправление: msvcrt предоставляет «библиотеку времени выполнения C», но сама по себе не является ядром языка. И в какой-то момент вы доходите до градусов: где провести черту между средой выполнения и ее отсутствием? Я считаю, что в C нет среды выполнения - нет сборки мусора, никаких других потоков, управляющих чем-либо, никаких автоматических функций. Нет системы типов времени выполнения. Ничего, кроме интерфейсов типа malloc, которые могут быть реализованы как фасад ОС, и, следовательно, если вы не рассматриваете саму ОС как «языковую среду выполнения», то C не имеет среды выполнения вообще.
на самом деле вы можете: операционная система предоставляет mmap, и в этом смысле она предоставляет распределитель для языков. он также иногда поддерживает sbrk и фиксацию страниц стека, сигнализацию доступа к странице с защитой стека, сигнализацию ошибок сегментации, sigbus, создание канала, создание потока, создание фильтра, поддержку переключателей контекста, абстракцию файловой системы, каналы ... для меня это огромное время выполнения.
Вы не можете по всей разумности считать, что ОС является ответственностью C++. Да, C++ обычно входит в состав ОС для приложений пользовательского уровня. А как насчет встроенных систем? А как насчет драйверов устройств? Сама ОС? Все программное обеспечение существует в какой-то экосистеме, но C++ не требует выполнения части кода для выполнения самого языка или поддержки своего ядра. Язык не требует этого. C++ можно скомпилировать и связать без каких-либо внешних ссылок). Вы можете по желанию использовать ОС-сервисы, а также можете использовать библиотеки C или C++. Необязательно + Вы.
«Среда выполнения C» - это просто динамическая библиотека, содержащая код стандартной библиотеки C. То же самое для «среды выполнения C++». Это сильно отличается от системы времени выполнения, такой как Objective-C. Кроме того ... хотя я полагаю, что вы могли бы технически использовать среду выполнения Objective-C на C, это все еще просто программа C, которая использует среду выполнения Objective-C - вы не можете скомпилировать настоящую программу Objective-C на C.
C++ 11, имеющий модель памяти + атомику, делает его более похожим на портативный ассемблер. Это не высокоуровневые вещи, это вещи уровня низкий, для которых C++ ранее не имел переносимой поддержки. Но количество UB в C++, если вы делаете что-то не так, делает его очень непохожим на языки на основе виртуальных машин, такие как Java, а также на любой конкретный язык ассемблера. например подписанное переполнение - это полностью UB в исходном коде C++ и компилятор может оптимизировать на основе этого факта, даже если компилируется, скажем, для x86, но в asm почти на всех платформах он просто оборачивается. Современный C++ очень далек от переносимого языка ассемблера.
Существует множество случаев использования отражения в C++, которые нельзя адекватно решить с помощью конструкций времени компиляции, таких как метапрограммирование шаблонов.
N3340 предлагает расширенные указатели как способ внедрения отражения в C++. Среди прочего, он решает проблему неоплаты за функцию, если вы ее не используете.
Отражение может быть необязательным, как директива препроцессора. Что-то вроде
#pragma enable reflection
Таким образом, мы можем получить лучшее из обоих миров, без этих библиотек прагм, которые будут создаваться без рефлексии (без каких-либо накладных расходов, как обсуждалось), тогда каждый разработчик будет решать, хотят ли они скорости или простоты использования.
Как это отвечает на фактически заданный вопрос?
Это в основном потому, что это «дополнительная опция». Многие люди предпочитают C++ таким языкам, как Java и C#, чтобы иметь больший контроль над выводом компилятора, например. меньшая и / или более быстрая программа.
Если вы решите добавить отражение, есть доступны различные решения.
C++ - это язык, который не нуждается в отражении, потому что C++ - это язык, который вы могли бы использовать для написания языка, в котором есть отражение.
С ++ может извлечь выгоду из отражения так же, как и любой другой язык. Дело в том, что эти преимущества прямо противоречат целям максимальной производительности и эффективности использования ресурсов.
RTTI соответствует стандарту C++.