Скажу, что автор комментариев пропустил один очевидно лажовый момент.
Item 31
Пример из вопроса:
namespace A
{
struct X;
struct Y;
void f( int );
void g( X );
}
namespace B
{
void f( int i )
{
f( i ); // which f()?
}
void g( A::X x )
{
g( x ); // which g()?
}
void h( A::Y y )
{
h( y ); // which h()?
}
}
Ответ.
Two of the three cases are (fairly) obvious, but the third requires a good knowledge of C++'s name lookup rules—in particular, Koenig lookup.
Let's start simple.
namespace A
{
struct X;
struct Y;
void f( int );
void g( X );
}
namespace B
{
void f( int i )
{
f( i ); // which f()?
}
This f() calls itself, with infinite recursion. The reason is that the only visible f() is B::f() itself.
There is another function with signature f(int), namely the one in namespace A. If B had written "using namespace A;" or "using A::f;", then A::f(int) would have been visible as a candidate when looking up f(int), and the f(i) call would have been ambiguous between A::f(int) and B::f(int). Since B did not bring A::f(int) into scope, however, only B::f(int) can be considered, so the call unambiguously resolves to B::f(int).
Выделенное — неверно.
Of course, the code must be complete enough to compile and link.
Здравствуйте, Greg Zubankov, Вы писали:
GZ>Комментарии к известной книге Саттера. GZ>здесь
GZ>Что скажете?
Это личные замечания Сергей Деревяго. Они так же подвержены неточностям, как и книга, которую он критикует (часто его замечания — просто придирки ). Например, его постоянные выпады в сторону find. Сергей не учитывает, что использовать find или нет, зависит от того сколько раз мы будем искать, если поиск будет всего один раз-два раза, то предварительная сортировка будет стоить существенно дороже, чем поиск сам поиск с помощью find. Кроме того, find подходит для всех контейнеров, даже для тех, у кого нет random-access итераторов (например, list, для него лучше линейного поиска тяжело что-то найти). Так что придраться можно ко всем, но, на мой взгляд, делать это не нужно...
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>There is another function with signature f(int), namely the one in namespace A. If B had written "using namespace A;" or "using A::f;", then A::f(int) would have been visible as a candidate when looking up f(int), and the f(i) call would have been ambiguous between A::f(int) and B::f(int). Since B did not bring A::f(int) into scope, however, only B::f(int) can be considered, so the call unambiguously resolves to B::f(int).
L_L>Выделенное — неверно.
Что конкретно не верно с твоей точки зрения? "using namespace A;" не будет приводить к неоднозначности так как имя будет доступно для поиска только в глобальном пространстве имен. Корректный пример с неоднозначностью будет выглядеть так:
namespace B {
namespace A {
void f( int );
}
using namespace A;
void f(int i) {
f(i);
}
}
Если написать "using A::f;" то при попытке объявления B::f будет выдаваться ошибка, так как функция с такой сигнатурой в пространстве имен B уже есть. А если бы ошибка на это не была выдана, то обнаружилась бы неоднозначность при вызове. "using A::f;" вводит имя в само пространство имен B, а не в объемлющий скоп как для случая "using namespace A;".
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Да, так, и то, что ты написал никак не совпадает с тем, что написал Саттер
L_L>
L_L>and the f(i) call would have been ambiguous between A::f(int) and B::f(int).
Честно сказать, я все равно не понял твоих возражений. Может быть я неверно перевел с английского .
Как я понял из цитаты
If B had written "using namespace A;" or "using A::f;", then A::f(int)
речь идет именно об использовании using директивы или декларации внутри namespace B. В таком случае действитеольно есть неоднозначность:
namespace A
{
void f( int );
}
namespace B
{
using A::f;
void f( int i )
{
f( i );
}
}
int main( void )
{}
Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++
"ComeauTest.c", line 10: error: function "B::f(int)" conflicts with
using-declaration of function "A::f(int)"
void f( int i )
^
1 error detected in the compilation of "ComeauTest.c".
По-моему, это вполне ожидаемое поведение. Так что я не вижу тут ошибки.
Здравствуйте, MuTPu4, Вы писали:
MTP>Честно сказать, я все равно не понял твоих возражений. Может быть я неверно перевел с английского . MTP>Как я понял из цитаты MTP>
MTP>If B had written "using namespace A;" or "using A::f;", then A::f(int)
MTP>речь идет именно об использовании using директивы или декларации внутри namespace B. В таком случае действитеольно есть неоднозначность:
В оригинале речь идет о неоднозначности при вызове. Если даже считать ошибку conflicts with using-declaration of function ... неоднозначностью при вызове, то уж при using namespace A; ее просто нету и тут уж явно неверное утверждение. От человека, который возглавляет(лял?) комитет по стандартизации и пишет книги типа "учитесь, как надо" можно ожидать большей точности и внимания к деталям. Вот еще пример из совместной книги с Александреску, сначала говорят (не помню номер Item'a) не полагайтесь в своих пограммах на особенности реализации (или что-то в этом роде), а затем перечисляют то, что стандарт гарантируют и говорят, в частности, что стандарт гарантирует для отрицательных целых two's complementary.
Of course, the code must be complete enough to compile and link.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Вот еще пример из совместной книги с Александреску, сначала говорят (не помню номер Item'a) не полагайтесь в своих пограммах на особенности реализации (или что-то в этом роде), а затем перечисляют то, что стандарт гарантируют и говорят, в частности, что стандарт гарантирует для отрицательных целых two's complementary.
Действительно так я даже тебе не поверил и полез в книгу проверять,
Chapter 91/Discussion:
The C++ Standard makes few guarantees about how types are represented in memory:
Base two is guaranteed for integral numbers.
Two's complement is guaranteed for negative integral numbers.
Plain Old Data (POD) types have C-compatible layout: Member variables are stored in their order of declaration.
int holds at least 16 bits.
Единственная догадка состоит в том, что имеет в виду преобразование знакового в беззнаковое, для отрицательных чисел оно происходит так, как будто бы в системе с дополнением до двух:
4.7/2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2^n where n is the number of bits used to represent the unsigned type). [Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note]
Здравствуйте, dupamid, Вы писали:
D>Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>>Вот еще пример из совместной книги с Александреску, сначала говорят (не помню номер Item'a) не полагайтесь в своих пограммах на особенности реализации (или что-то в этом роде), а затем перечисляют то, что стандарт гарантируют и говорят, в частности, что стандарт гарантирует для отрицательных целых two's complementary.
D>Действительно так я даже тебе не поверил и полез в книгу проверять,
Это правильно, верить на слово никогда не стоит. Ну или почти никогда
D>Единственная догадка состоит в том, что имеет в виду преобразование знакового в беззнаковое, для отрицательных чисел оно происходит так, как будто бы в системе с дополнением до двух:
Все же не хотелось бы подобных неоднозначностей.
Of course, the code must be complete enough to compile and link.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>В оригинале речь идет о неоднозначности при вызове. Если даже считать ошибку conflicts with using-declaration of function ... неоднозначностью при вызове, то уж при using namespace A; ее просто нету и тут уж явно неверное утверждение.
Спасибо за пояснения, ты и dupamid абсолютно правы, неоднозначность тут возникает при декларации B::f. Кстати, MSVC обрабатывает этот случай неправильно.