Подтвердить что ты не робот

Является std::vector <T> "определяемым пользователем типом"?

В 17.6.4.2.1/1 и 17.6.4.2.1/2 текущий проект стандарта устанавливаются ограничения по специализациям, введенным пользователей в namespace std.

Поведение C ++ программа undefined, если она добавляет объявления или определения в пространство имен станд или пространство имен в пространстве имен станд если не указано иное. Программа может добавить специализацию шаблона для любого стандартного шаблона библиотеки для пространства имен станд только если декларация зависит от пользовательского типаи специализация соответствует стандартным требованиям библиотеки для исходного шаблона и не является явно запрещено.

Я не могу найти, где в стандарте определена фраза определяемый пользователем тип.

Один из вариантов, о котором я слышал, состоит в том, что тип std::is_fundamental не является определяемым пользователем типом, и в этом случае std::vector<int> будет определяемым пользователем типом.

Альтернативным ответом будет то, что пользовательский тип - это тип, который пользователь определяет. Поскольку пользователи не определяют std::vector<int>, а std::vector<int> не зависит от любого типа, который определяет пользователь, std::vector<int> не является определяемым пользователем типом.

Практическая проблема заключается в том, что "можете ли вы ввести специализацию для std::hash для std::tuple<Ts...> в namespace std? Возможность сделать это несколько удобна - альтернативой является создание другого пространства имен, в котором мы рекурсивно создаем нашу hash для std::tuple (и, возможно, других типов в std, у которых нет поддержки hash), и тогда и только тогда, когда нам не удается найти хэш в этом пространстве имен, мы возвращаемся к std.

Однако, если это законно, то, если и когда стандарт добавляет специализацию hash для std::tuple в namespace std, код, который его специализировал, будет нарушен, создавая причину не добавлять такие специализации в будущее.

Пока я говорю о std::vector<int> как конкретном примере, я пытаюсь спросить, являются ли типы, определенные в std, определяемым пользователем типом. Второй вопрос, даже если нет, может быть, std::tuple<int> становится определяемым пользователем типом при использовании пользователем (это становится скользким: что тогда происходит, если что-то внутри std определяет std::tuple<int>, и вы частично-специализируете hash для std::tuple<Ts...>).


В настоящее время существует проблема открыть дефект по этой проблеме.

4b9b3361

Ответ 1

Prof. Stroustrup очень ясно, что любой тип, который не встроен, определяется пользователем. См. Второй абзац раздела 9.1 "Принципы и практика программирования с использованием С++".

Он даже специально вызывает "стандартные типы библиотек" в качестве примера пользовательских типов. Другими словами, пользовательский тип является любым составным типом.

Источник

В статье явно упоминается, что не все, похоже, согласны, но это ИМХО в основном принятие желаемого за действительное, а не то, что на самом деле говорят стандарт (и проф. Страуструп), только то, что некоторые люди хотят прочитать в нем.

Ответ 2

Когда в разделе 17 указано "определяемое пользователем", это означает "тип, не определенный в стандарте", поэтому std::vector<int> является не пользователем, а не std::string, поэтому вы не можете специализироваться std::vector<int> или std::vector<std::string>. С другой стороны, struct MyClass определяется пользователем, потому что это не тип, определенный в стандарте, поэтому вы можете специализировать std::vector<MyClass>.

Это не то же значение, что и "пользовательские", используемые в пунктах 1-16, и эта разница является запутанной и глупой. Для этого есть отчет о дефектах, с некоторым обсуждением, которое в основном говорит: "Да, библиотека использует неправильный термин, но у нас нет лучший".

Итак, ответ на ваш вопрос - "это зависит". Если вы говорите с разработчиком компилятора С++ или специалистом по основному языку, std::vector<int> определенно является определяемым пользователем типом, но если вы говорите со стандартным разработчиком библиотеки, это не так. Точнее, он не определяется пользователем для целей 17,6.4.2.1.

Один из способов взглянуть на это состоит в том, что стандартная библиотека - это "код пользователя" в отношении основного языка. Но стандартная библиотека имеет другую идею "пользователей" и считает себя частью реализации, и только те вещи, которые не являются частью библиотеки, являются "определяемыми пользователем".

Изменить: Я предложил изменить библиотечные Клаузы для использования нового термина "с программным определением", что означает что-то определенное в вашей программе (в отличие от UDT, определенных в стандарте, например std::string).

Ответ 3

Поскольку пользователи не определяют std::vector<int>, а std::vector<int> не зависит от любого типа, который определяет пользователь, std::vector<int> не является определяемым пользователем типом.

Аргумент логического счетчика состоит в том, что пользователи do определяют std::vector<int>. Вы видите, что std::vector является шаблоном класса и как таковой не имеет прямого представления в двоичном коде.

В некотором смысле он получает это двоичное представление через экземпляр типа, поэтому само действие объявления объекта std::vector<int> - это то, что дает "душу" шаблону (помилование фразы). В программе, где никто не использует std::vector<int>, этот тип данных не существует.

С другой стороны, по тому же аргументу std::vector<T> является не определяемым пользователем типом, он даже не является типом, его не существует; только если мы хотим (создать экземпляр типа), , он выделит, как структура будет выложена, но до этого мы можем только утверждать об этом в терминах структуры, дизайн, свойства и т.д.

Примечание

Вышеприведенный аргумент (о шаблонах, а не о коде, но... шаблонах для кода) может показаться немного поверхностным, но делает его логичным, начиная с введения Майера в книге Александра Александреску Modern С++ Design. Относительная цитата там выглядит следующим образом:

В конце концов, Андрей обратил внимание на разработку шаблонных реализаций популярных языковых идиом и шаблонов дизайна, особенно шаблонов GoF [*]. Это привело к кратковременной стычке с сообществом Patterns, , потому что один из их основных принципов состоит в том, что шаблоны не могут быть представлены в коде. Как только стало ясно, что Андрей автоматизировал создание реализаций шаблонов, а не пытался кодировать сами шаблоны, это возражение было удалено, и я был рад видеть, что Андрей и один из GoF (John Vlissides) сотрудничают на двух столбцах в отчете С++, посвященном работе Андрея.

Ответ 4

Проект стандарта контрастирует основные типы с пользовательскими типами в нескольких (ненормативных) местах.

В стандарте проекта также используется термин "определяемый пользователем" в других контекстах, относящийся к объектам, созданным программистом или определенным в стандартной библиотеке. Примеры включают пользовательский конструктор, пользовательский оператор и пользовательское преобразование.

Эти факты позволяют нам, если не считать других доказательств, предварительно предположить, что целью стандарта является то, что определяемый пользователем тип должен означать составной тип, согласно историческому использованию. Только явное разъяснение в будущем стандартном документе может определенно решить проблему.

Обратите внимание, что историческое использование неясно в таких типах, как int* или struct foo* или void(*)(struct foo****). Они сложны, но должны ли они (или некоторые из них) считаться определяемыми пользователем?