Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Ты, я вижу, даже не попытался понять, кому и на что ответил saproj
СИЛЬНО извиняюсь
L_L>Возьми исходный пример автора топика, который...
а ты когда тему просматриваешь, наверное в начало не смотришь?..
(http://www.rsdn.ru/forum/cpp/3519299.1.aspx
)
L>И я не понимаю, это у меня с недосыпа с головой что-то и я не заметил чего-то, или тут, в этом флеймище люди о каком-то другом языке программирования рассуждают? Какие-то консты в параметры шаблона суют, еще чего-то, историю авто птр вспоминают...
я тоже не люблю усложнять
Alexander G:
E>>А какой в этом смысл? Чем rvalue T* отличается от Т*const ? AG>+ AG>тут та самая тонкость, что int * const f() и int * f() — одна и та же функция.
Это разные функции (в отличие от параметров, cv-квалификация типа возврата в типе функции никогда не удаляется). Причём стандарт в отношении результата вызова первой функции противоречив: с одной стороны он утверждает, что
"non-class rvalues always have cv-unqualified types" (3.10/9)
с другой — что
"The type of the function call expression is the return type of the statically chosen function" (5.2.2/3) — никакого упоминания о снятии cv-квалификации.
Вот такой пример
int * const f();
typedef char one[1];
typedef char two[2];
one &g(int const *);
template <class T>
two &g(T &);
int main()
{
char arr[sizeof g(f()) - 1];
}
успешно компилируется VC++ 8.0 и GNU C++ 4.1.2 (они считают, что f() имеет тип int * const, и выбирают вторую g) и не компилируется Intel C++ 11.0 и Comeau (они считают, что f() имеет тип int *, и выбирают первую g).
Здравствуйте, Кодт, Вы писали:
К>Естественно, что над константой нет оператора автоинкремента.
К>Или ты хочешь сказать, что код К>
К>int* p = auto_ptr<const int>(new int(123));
К>
К>удачно скомпилировался?! К>Ну, выкини в топку свою версию STL, что ли.
Я написал в точности наоборот
const std::auto_ptr<int> ap(new int(123));
++*ap;
скомпилировался, автоинкримент не над константой и должен компилироватся. А operator* и get() почему компилируются неясно http://msdn.microsoft.com/en-us/library/b84a89af(VS.71).aspx не говорит что они константные. Правда const std::auto_ptr<int> не дает один ptr другому присвоить.
А зачем не дать? Собственно это и был мой вопрос. Смотри, ap у тебя объявлен как auto_ptr<int>, а не как auto_ptr<int const>, соответственно auto_ptr::get возвращает int*, а не int const*. Почему же get_ptr должен вводить дополнительное ограничение?
Да, не сочти за поучение, просто на всякий случай: const у auto_ptr в твоем примере делает константным указатель, а не то, на что тот указывает.
Здравствуйте, igna, Вы писали:
I>Читаю книгу Matthew Wilson, Imperfect C++ и на странице 344...
I>В чем смысл этой перегрузки, почему вместо двух шаблонов не использовать один?:
Никакого смысла нет. (В начале я начал отвечать на этот пост, будучи уверенным, что смысл есть. Но по ходу того, как я пытался его объяснить, мне стало понятно, что никакого смысла нет.)
Wilson на этой странице пишет про так называемые шимы (shims). Shim — это, грубо говоря, простейший адаптер, который на короткое время сводит разные (но близкие по смыслу) интерфейсы к одному общему путём создания временного объекта.
Шимы могут быть различного характера:
* attribute — предостваляющие доступ к внутреннему свойству объекта
* control — позволяющие выполнить какое-нибудь действие над объектом
* conversion — переводящие к другому (не сходному) типу
и т.д.
get_ptr — это шим, предназначение которого — предоставлять доступ к внутреннему указателю для различных смарт поинтеров. В таком случае, вопрос нужно задать следующий: по смыслу (а не по техническим причинам), какой тип указателя содержится в (и нужно возвратить из) auto_ptr<T> и auto_ptr<T> const? Ясно, что тип указателя у них один и тот же — T*. Поэтому достаточно одной функции: T * get_ptr(auto_ptr<T> const &), а Wilson просто ошибся.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, igna, Вы писали:
I>>В чем смысл этой перегрузки, почему вместо двух шаблонов не использовать один?:
AG>Я считаю, просто дело привычки писать две версии в подобных случаях, написано неправильно "на автомате". AG>Если бы это было задумано, const вариант был бы консистентен:
AG>
Chorkov:
C>ИМХО C>std::auto_ptr<T const > C>Лишен смысла, поскольку поскольку не имеет права сделать delete, подконтрольному объекту.
Почему?
C>std::auto_ptr<T> const &p C>опасен, поскольку компилятор имеет право создать копию std::auto_ptr<T>, C>что приведет к преждевременному разрушению объекта.
Здравствуйте, Николай Ивченков, Вы писали:
НИ>Chorkov:
C>>ИМХО C>>std::auto_ptr<T const > C>>Лишен смысла, поскольку поскольку не имеет права сделать delete, подконтрольному объекту. НИ>Почему?
C>>std::auto_ptr<T> const &p C>>опасен, поскольку компилятор имеет право создать копию std::auto_ptr<T>, C>>что приведет к преждевременному разрушению объекта.
НИ>Хотелось бы увидеть конкретный пример.
Был неправ в обоих случаях.
Полагал раз по указателю на константный объект нельзя изменить состояние объекта, то его нельзя и разрушить (сменить состояние на "разрушенный"). Типа, константных деструкторов не существует.
Однако, примечание к 5.3.5/2 меня разубедило.
Во втором случае — вообще не понимаю что на меня нашло.
Подразумевалась создание временного объекта, при "r-value to reference".
Chorkov:
C>Подразумевалась создание временного объекта, при "r-value to reference".
С такой инициализацией проблема есть, но заключается она только в том, что программа может не скомпилироваться вообще. В стандарте говорится, что может быть создан дополнительный временный объект, но не говорится, какие конструкторы могут участвовать в его создании. Если конструктор auto_ptr(auto_ptr_ref<X>) не входит в set of candidate functions, то такая инициализация ill-formed; если же он входит в set of candidate functions, то он будет и viable function и тогда ошибки нет.
VC++ 8.0 с /Za, GNU C++ 4.1.2 и Comeau C++ с отключенными расширениями C++0x ругаются на такое reference binding.
НИ>Причём стандарт в отношении результата вызова первой функции противоречив: с одной стороны он утверждает, что
НИ>"non-class rvalues always have cv-unqualified types" (3.10/9)
НИ>с другой — что
НИ>"The type of the function call expression is the return type of the statically chosen function" (5.2.2/3) — никакого упоминания о снятии cv-квалификации.
"Никакого упоминания" — не означает, что снятия cv-квалификации не выполняется; ее необходимость неявно следует из твоей первой цитаты.
Стандарт в этом месте туманен, но все-таки не противоречив.
Roman Odaisky:
НИ>>int * const f(); НИ>>one &g(int const *);
НИ>>считают, что f() имеет тип int * const, и выбирают вторую g
RO>Там точно все const на своих местах?
Да. Впрочем, можно было и проще пример взять:
int * const f();
template <class T>
int g(T &);
int main()
{
sizeof g(f());
}
Похоже, здесь, если убрать const в типе возврата f, VC++ своё фирменное расширение (возможность инициализации rvalue-выражением ссылки на non-const) всё равно не применяет.
igna:
НИ>>"The type of the function call expression is the return type of the statically chosen function" (5.2.2/3) — никакого упоминания о снятии cv-квалификации.
I>"Никакого упоминания" — не означает, что снятия cv-квалификации не выполняется; ее необходимость неявно следует из твоей первой цитаты.
Это домыслы. Например, int и const int — это два разных типа. Если "return type of the statically chosen function" — это const int, а "type of the function call expression" — это int, то правило 5.2.2/3 в буквальной интерпретации не соблюдается — так же, как если бы в качестве "type of the function call expression" выступал бы какой-нибудь long.
I>Стандарт в этом месте туманен, но все-таки не противоречив.
Следуя 5.2.2/3 буквально, мы приходим к противоречию с 3.10/9.
Здравствуйте, Николай Ивченков, Вы писали:
НИ>Следуя 5.2.2/3 буквально, мы приходим к противоречию с 3.10/9.
Хорошо. Ты можешь представить себе, что когда это противоречие в стандарте снимут, выиграет 5.2.2/3, а не 3.10/9? То есть, что "non-class rvalues" смогут иметь "cv-qualified types"?
igna:
НИ>>Следуя 5.2.2/3 буквально, мы приходим к противоречию с 3.10/9.
I>Хорошо. Ты можешь представить себе, что когда это противоречие в стандарте снимут, выиграет 5.2.2/3, а не 3.10/9? То есть, что "non-class rvalues" смогут иметь "cv-qualified types"?
От комитета по стандартизации C++ можно ожидать чего угодно. Вот он годами работает над стандартом, а в итоге всё равно получается куча очевидных нестыковок. Как так выходит?