VC|++ 2005
От: Шахтер Интернет  
Дата: 08.10.05 17:23
Оценка:
Поставил себе бету. Сразу напоролся на два бага.


/* test1.cpp */ 

#include <iostream>

using namespace std;

/* Bug1 */ 

class A {};

class B : A
 {
 };

class C : public B
 {
  public:
  
   class I : A {};
 };

.\test1.cpp(19) : error C2247: 'A' not accessible because 'B' uses 'private' to inherit from 'A'
        .\test1.cpp(9) : see declaration of 'A'
        .\test1.cpp(11) : see declaration of 'B'
        .\test1.cpp(9) : see declaration of 'A'

 
/* Bug2 */  

template <class T>
struct Foo
 {
 };
 
template <size_t N> 
struct Foo<const char[N]>
 {
  enum { Ret=100 };
 };
 
template <class T,size_t N> 
struct Foo<const T[N]>
 {
 };
 
template <class T> 
int GetFoo(const T &)
 {
  return Foo<T>::Ret;
 }

/* main() */ 

int main()
 {
  cout << GetFoo("12345") << endl ;
 
  return 0;
 }
 
.\test1.cpp(43) : error C2752: 'Foo<T>' : more than one partial specialization matches the template argument list
        with
        [
            T=const char [6]
        ]
        .\test1.cpp(38): could be 'Foo<const T[N]>'
        .\test1.cpp(33): or 'Foo<const char [N]>'
        .\test1.cpp(50) : see reference to function template instantiation 'int GetFoo<const char[6]>(T (&))' being compiled
        with
        [
            T=const char [6]
        ]
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: VC|++ 2005
От: the_void Швейцария  
Дата: 08.10.05 18:02
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Поставил себе бету. Сразу напоролся на два бага.


<skip>

Первая ошибка вроде вполне законна Comeau этот код не компилирует.
Вторая ошибка не воспроизводится (VC 8.0 beta 2).
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: VC|++ 2005
От: Шахтер Интернет  
Дата: 09.10.05 13:40
Оценка: -1
Здравствуйте, the_void, Вы писали:

_>Здравствуйте, Шахтер, Вы писали:


Ш>>Поставил себе бету. Сразу напоролся на два бага.


_><skip>


_>Первая ошибка вроде вполне законна Comeau этот код не компилирует.


Позор Comeau.

_>Вторая ошибка не воспроизводится (VC 8.0 beta 2).


Компилируй по отдельности каждый баг.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: VC|++ 2005
От: MaximE Великобритания  
Дата: 09.10.05 15:55
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, the_void, Вы писали:


_>>Здравствуйте, Шахтер, Вы писали:


Ш>>>Поставил себе бету. Сразу напоролся на два бага.


_>><skip>


_>>Первая ошибка вроде вполне законна Comeau этот код не компилирует.


Ш>Позор Comeau.


Comeau прав, это твоя ошибка.
Re[4]: VC|++ 2005
От: chp Россия  
Дата: 10.10.05 05:46
Оценка:
Здравствуйте, MaximE, Вы писали:
ME>Comeau прав, это твоя ошибка.
А поподробнее пожалуйста?
Re[4]: VC|++ 2005
От: Шахтер Интернет  
Дата: 10.10.05 06:34
Оценка: +1
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, Шахтер, Вы писали:


Ш>>Здравствуйте, the_void, Вы писали:


_>>>Здравствуйте, Шахтер, Вы писали:


Ш>>>>Поставил себе бету. Сразу напоролся на два бага.


_>>><skip>


_>>>Первая ошибка вроде вполне законна Comeau этот код не компилирует.


Ш>>Позор Comeau.


ME>Comeau прав, это твоя ошибка.


С какого это перепугу он прав?
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: VC|++ 2005
От: Lorenzo_LAMAS  
Дата: 10.10.05 08:33
Оценка: 7 (3)
Ш>С какого это перепугу он прав?
Почитай про поиск имен, а потом про доступ. Если напишешь ::А то скомпилит.
Of course, the code must be complete enough to compile and link.
Re[5]: VC|++ 2005
От: MaximE Великобритания  
Дата: 10.10.05 08:34
Оценка: 2 (2)
On Mon, 10 Oct 2005 10:34:15 +0400, Шахтер <23118@users.rsdn.ru> wrote:

> Здравствуйте, MaximE, Вы писали:

>
> ME>Здравствуйте, Шахтер, Вы писали:
>
> Ш>>Здравствуйте, the_void, Вы писали:
>
> _>>>Здравствуйте, Шахтер, Вы писали:
>
> Ш>>>>Поставил себе бету. Сразу напоролся на два бага.
>
> _>>><skip>
>
> _>>>Первая ошибка вроде вполне законна Comeau этот код не компилирует.
>
> Ш>>Позор Comeau.
>
> ME>Comeau прав, это твоя ошибка.
>
> С какого это перепугу он прав?

3.4.1 Unqualified name lookup [basic.lookup.unqual]
1 In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.
...
7 A name used in the definition of a class X outside of a member function body or nested class definition shall be declared in one of the following ways:
...
— if X is a nested class of class Y (9.7), before the definition of X in Y, or shall be a member of a base class of Y (this lookup applies in turn to Y’s enclosing classes, starting with the innermost enclosing class)
or
...


Т.е. здесь применяется обычный name lookup. Определение базового класса А для вложенного класса C::I ищется согласно 3.4.1 сначала в C, затем в базовых классах C. Это имя находится в scope'e базового класса B. Как только имя найдено процесс поиска имени закончен. Далее делается проверка доступа и завершается с ошибкой, так как A — private базовый класс B.

Тонкость, которую не стоит упускать: поиск имени и проверка доступа — последовательные независимые этапы.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[6]: VC|++ 2005
От: Шахтер Интернет  
Дата: 10.10.05 15:50
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>On Mon, 10 Oct 2005 10:34:15 +0400, Шахтер <23118@users.rsdn.ru> wrote:


>> Здравствуйте, MaximE, Вы писали:

>>
>> ME>Здравствуйте, Шахтер, Вы писали:
>>
>> Ш>>Здравствуйте, the_void, Вы писали:
>>
>> _>>>Здравствуйте, Шахтер, Вы писали:
>>
>> Ш>>>>Поставил себе бету. Сразу напоролся на два бага.
>>
>> _>>><skip>
>>
>> _>>>Первая ошибка вроде вполне законна Comeau этот код не компилирует.
>>
>> Ш>>Позор Comeau.
>>
>> ME>Comeau прав, это твоя ошибка.
>>
>> С какого это перепугу он прав?

ME>

ME>3.4.1 Unqualified name lookup [basic.lookup.unqual]
ME>1 In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.
ME>...
ME>7 A name used in the definition of a class X outside of a member function body or nested class definition shall be declared in one of the following ways:
ME>...
ME>— if X is a nested class of class Y (9.7), before the definition of X in Y, or shall be a member of a base class of Y (this lookup applies in turn to Y’s enclosing classes, starting with the innermost enclosing class)
ME>or
ME>...


ME>Т.е. здесь применяется обычный name lookup. Определение базового класса А для вложенного класса C::I ищется согласно 3.4.1 сначала в C, затем в базовых классах C. Это имя находится в scope'e базового класса B. Как только имя найдено процесс поиска имени закончен. Далее делается проверка доступа и завершается с ошибкой, так как A — private базовый класс B.


Класс A определён не в scope класса B, а в глобальном scope. Его полное имя ::A, а не ::B::A. Так что не проходит твоё рассуждение.
Но дело даже не в этом -- сама ситуация абсурдна, когда некий промежуточный класс переквалифицировал возможность использования класса из глобалбного пространства имен.

ME>Тонкость, которую не стоит упускать: поиск имени и проверка доступа — последовательные независимые этапы.


ME>--

ME>Maxim Yegorushkin
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[6]: VC|++ 2005
От: Шахтер Интернет  
Дата: 10.10.05 15:52
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

Ш>>С какого это перепугу он прав?

L_L>Почитай про поиск имен, а потом про доступ. Если напишешь ::А то скомпилит.

A и ::A обозначают одну и ту же сущность -- класс A определённый в глобальном пространстве имен.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: VC|++ 2005
От: MaximE Великобритания  
Дата: 10.10.05 18:04
Оценка:
On Mon, 10 Oct 2005 19:50:13 +0400, Шахтер <23118@users.rsdn.ru> wrote:

[]

> ME>Т.е. здесь применяется обычный name lookup. Определение базового класса А для вложенного класса C::I ищется согласно 3.4.1 сначала в C, затем в базовых классах C. Это имя находится в scope'e базового класса B. Как только имя найдено процесс поиска имени закончен. Далее делается проверка доступа и завершается с ошибкой, так как A — private базовый класс B.

>
> Класс A определён не в scope класса B, а в глобальном scope. Его полное имя ::A, а не ::B::A.

Это так.

> Так что не проходит твоё рассуждение.


Подходит, читай ниже.

> Но дело даже не в этом -- сама ситуация абсурдна, когда некий промежуточный класс переквалифицировал возможность использования класса из глобалбного пространства имен.


Вот здесь корень твоего заблуждения. Именно в этом вся суть пространств имен — чтобы в них можно было объявлять те же имена, что и в других scope'aх. Class — это то же (кастрированное) пространство имен.

Поиск неквалифицированных имен не ищет объявление. Он ищет первый scope, в котором это имя доступно. scope, в котором имя объявлено, всего лишь один, в которых оно доступно — один и более.

Считаешь ли ты такую ситуацию абсурдной:

struct A {};

namespace B
{
     struct A {};

     namespace C
     {
         struct I : A {}; // I derives B::A, not ::A
     }
}


?

P.S. Вобщем-то, мне все равно, что ты считаешь — меня не беспокоит чужое неправильное понимание, отвечать в этом треде я больше не буду.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[8]: VC|++ 2005
От: Шахтер Интернет  
Дата: 11.10.05 11:12
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>On Mon, 10 Oct 2005 19:50:13 +0400, Шахтер <23118@users.rsdn.ru> wrote:


ME>[]


>> ME>Т.е. здесь применяется обычный name lookup. Определение базового класса А для вложенного класса C::I ищется согласно 3.4.1 сначала в C, затем в базовых классах C. Это имя находится в scope'e базового класса B. Как только имя найдено процесс поиска имени закончен. Далее делается проверка доступа и завершается с ошибкой, так как A — private базовый класс B.

>>
>> Класс A определён не в scope класса B, а в глобальном scope. Его полное имя ::A, а не ::B::A.

ME>Это так.


>> Так что не проходит твоё рассуждение.


ME>Подходит, читай ниже.


>> Но дело даже не в этом -- сама ситуация абсурдна, когда некий промежуточный класс переквалифицировал возможность использования класса из глобалбного пространства имен.


ME>Вот здесь корень твоего заблуждения. Именно в этом вся суть пространств имен — чтобы в них можно было объявлять те же имена, что и в других scope'aх. Class — это то же (кастрированное) пространство имен.


ME>Поиск неквалифицированных имен не ищет объявление.


Противоречие однако. Если суть -- в возможности объявлять, то и искаться должны объявления.

ME>Он ищет первый scope, в котором это имя доступно. scope, в котором имя объявлено, всего лишь один, в которых оно доступно — один и более.


ME>Считаешь ли ты такую ситуацию абсурдной:


ME>
ME>struct A {};

ME>namespace B
ME>{
ME>     struct A {};

ME>     namespace C
ME>     {
ME>         struct I : A {}; // I derives B::A, not ::A
ME>     }
ME>}
ME>


ME>?


Эта ситуация нормальна -- именно потому, что пространство имен B объявляет своё имя A, которое скрывает имя, определённое в глобальном scope. В моём же случае этого нет. И в этом большая разница.

ME>P.S. Вобщем-то, мне все равно, что ты считаешь — меня не беспокоит чужое неправильное понимание, отвечать в этом треде я больше не буду.


Спасибо за потраченное на ответы время.

ME>--

ME>Maxim Yegorushkin
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: VC|++ 2005
От: Павел Кузнецов  
Дата: 11.10.05 22:03
Оценка:
Шахтер,

>
> /* Bug1 */
>
> class A {};
>
> class B : A { };
>
> class C : public B
>  {
>   public:
>    class I : A {};
>  };
>


>
> .\test1.cpp(19) : error C2247: 'A' not accessible because 'B' uses 'private' to inherit from 'A'
>         .\test1.cpp(9) : see declaration of 'A'
>         .\test1.cpp(11) : see declaration of 'B'
>         .\test1.cpp(9) : see declaration of 'A'
>


Это не баг, это следствие базовых положений:
  • проверка доступа контролируется на уровне имен, а не обозначаемых ими сущностей;
  • имя класса впрыскивается в его scope и наследуется;
  • имя из class scope перекрывает имена из global scope.

    Почему полезно впрыскивать имя класса в его scope.

    Помимо прочего, для того, чтобы имя обозначало один и тот же класс, как в списке базовых классов, так и внутри класса. Например:

    Без впрыскивания имени класса в его scope: http://tydbits.org/node/61
    С впрыскиванием имени класса в его scope: http://tydbits.org/node/62
    Posted via RSDN NNTP Server 2.0 beta
  • Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
    Re[7]: VC|++ 2005
    От: Lorenzo_LAMAS  
    Дата: 12.10.05 07:07
    Оценка:
    Ш>A и ::A обозначают одну и ту же сущность -- класс A определённый в глобальном пространстве имен.

    Несомненно. Вот только просто А будет найдено как имя где-то в базовых классах, да еще и закрытое, а ::А будет сразу искаться в глобальном пространстве имен.
    Of course, the code must be complete enough to compile and link.
    Re[2]: VC|++ 2005
    От: Шахтер Интернет  
    Дата: 12.10.05 10:13
    Оценка: -1
    Здравствуйте, Павел Кузнецов, Вы писали:

    ПК>Шахтер,


    >>
    >> /* Bug1 */
    >>
    >> class A {};
    >>
    >> class B : A { };
    >>
    >> class C : public B
    >>  {
    >>   public:
    >>    class I : A {};
    >>  };
    >>


    >>
    >> .\test1.cpp(19) : error C2247: 'A' not accessible because 'B' uses 'private' to inherit from 'A'
    >>         .\test1.cpp(9) : see declaration of 'A'
    >>         .\test1.cpp(11) : see declaration of 'B'
    >>         .\test1.cpp(9) : see declaration of 'A'
    >>


    ПК>Это не баг, это следствие базовых положений:

    ПК>
  • проверка доступа контролируется на уровне имен, а не обозначаемых ими сущностей;
    ПК>
  • имя класса впрыскивается в его scope и наследуется;
    ПК>
  • имя из class scope перекрывает имена из global scope.

    Спасибо, я уже тоже нашел.

    ПК>Почему полезно впрыскивать имя класса в его scope.


    Полезно, согласен. Но в данном случае, однако, получается фигня-с -- хвост вылез, клюв застрял. Надо дефект репорт писать.

    Например, добавить в пункт 3.4 3 следующее положение про применение правил доступа.

    The injected-class-name of a class (clause 9) is also considered to be a member of that class for the purposes
    of name hiding and lookup.

    To check accessibility of this name access rules are applyed not to the injected-class-name, but to the original class name.

    Как ты на это смотришь?
  • В XXI век с CCore.
    Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
    Re[2]: VC|++ 2005
    От: Andrew S Россия http://alchemy-lab.com
    Дата: 12.10.05 11:36
    Оценка:
    ПК>С впрыскиванием имени класса в его scope: http://tydbits.org/node/62

    Павел, а можно привести разъяснения для С++ варианта? Очень заинтриговало
    http://www.rusyaz.ru/pr — стараемся писАть по-русски
    Re[3]: VC|++ 2005
    От: Шахтер Интернет  
    Дата: 13.10.05 11:15
    Оценка:
    Здравствуйте, Andrew S, Вы писали:

    ПК>>С впрыскиванием имени класса в его scope: http://tydbits.org/node/62


    AS>Павел, а можно привести разъяснения для С++ варианта? Очень заинтриговало



    template <class T1>
    struct A
     {
      T1 a;
    
      template <class T2>
      struct B : A<T2>       // (1)
       {
        T1 b;
    
        template <class T3>
        struct C : B<T3>     // Что означает B здесь?
         {
          T1 c;
         };
       }; 
     };


    B в указанной точке должно означать A<что-то>::B.

    Есть два варианта. Первый(правильный) -- A<T1>::B.
    Второй -- A<T2>::B. Второй вариант получается из-за наследования (1).
    Срабатывает первый вариант, потому что в scope B вводится имя B -- A<T1>::B, которое перекрывает имя, унаследованное из базового класса. В С# происходит обратное.

    Здесь правда есть ещё одна тонкость -- независимые имена. В декларации класса C имя B может быть связано только с именем A<T1>::B, поскольку имя A<T2>::B, унаследованное из A<T2>, найдено быть не может в точке декларации шаблона.
    Так что в C++ дело не доходит даже до сокрытия имени.
    В XXI век с CCore.
    Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
    Re[4]: VC|++ 2005
    От: Andrew S Россия http://alchemy-lab.com
    Дата: 13.10.05 13:51
    Оценка:
    Ш>
    Ш>template <class T1>
    Ш>struct A
    Ш> {
    Ш>  T1 a;
    
    Ш>  template <class T2>
    Ш>  struct B : A<T2>       // (1)
    Ш>   {
    Ш>    T1 b;
    
    Ш>    template <class T3>
    Ш>    struct C : B<T3>     // Что означает B здесь?
    Ш>     {
    Ш>      T1 c;
    Ш>     };
    Ш>   }; 
    Ш> };
    Ш>


    Ш>B в указанной точке должно означать A<что-то>::B.


    Ш>Есть два варианта. Первый(правильный) -- A<T1>::B.

    Ш>Второй -- A<T2>::B. Второй вариант получается из-за наследования (1).
    Ш>Срабатывает первый вариант, потому что в scope B вводится имя B -- A<T1>::B, которое перекрывает имя, унаследованное из базового класса. В С# происходит обратное.

    Разве тут дело в сокрытии? Что тут может (в случае С++) скрываться, если B — это шаблонный класс, соответственно для каждого типа генерируется свой инстанс. По-моему, дело в том, как определяется параметр T1.
    Попробуем инстанцировать A<int>::B<bool>::C<char>:

    1. A<int> = A_int
    2. A_int::B<char> = B_int_A_char
    3. B_int_A_char::C<bool> = C_int_B_int_A_bool

    Очевидно, что тут T1 определяется из внешнего по отношению к типу неймспейса, которым в данном случае на всех шагах служит А (поскольку в параметрах B и С мы T1, естественно, не находим).

    Ш>Здесь правда есть ещё одна тонкость -- независимые имена. В декларации класса C имя B может быть связано только с именем A<T1>::B, поскольку имя A<T2>::B, унаследованное из A<T2>, найдено быть не может в точке декларации шаблона.

    Ш>Так что в C++ дело не доходит даже до сокрытия имени.

    Про то и речь. О каком сокрытии имен может идти речь, если тут шаблонные классы. На мой взгляд, все дело в лукапе параметров шаблона. Лучше пусть ПК объяснит, это все он виноват
    http://www.rusyaz.ru/pr — стараемся писАть по-русски
    Re[8]: VC|++ 2005
    От: remark Россия http://www.1024cores.net/
    Дата: 13.10.05 14:05
    Оценка:
    Здравствуйте, MaximE, Вы писали:

    ME>On Mon, 10 Oct 2005 19:50:13 +0400, Шахтер <23118@users.rsdn.ru> wrote:


    ME>[]


    >> ME>Т.е. здесь применяется обычный name lookup. Определение базового класса А для вложенного класса C::I ищется согласно 3.4.1 сначала в C, затем в базовых классах C. Это имя находится в scope'e базового класса B. Как только имя найдено процесс поиска имени закончен. Далее делается проверка доступа и завершается с ошибкой, так как A — private базовый класс B.

    >>
    >> Класс A определён не в scope класса B, а в глобальном scope. Его полное имя ::A, а не ::B::A.

    ME>Это так.


    >> Так что не проходит твоё рассуждение.


    ME>Подходит, читай ниже.


    >> Но дело даже не в этом -- сама ситуация абсурдна, когда некий промежуточный класс переквалифицировал возможность использования класса из глобалбного пространства имен.


    ME>Вот здесь корень твоего заблуждения. Именно в этом вся суть пространств имен — чтобы в них можно было объявлять те же имена, что и в других scope'aх. Class — это то же (кастрированное) пространство имен.


    ME>Поиск неквалифицированных имен не ищет объявление. Он ищет первый scope, в котором это имя доступно. scope, в котором имя объявлено, всего лишь один, в которых оно доступно — один и более.



    Придётся ещё раз ответить
    Не доступно, а видимо. Это принципиальная разница. Если он искал доступное имя, то нашёл бы как раз ::A.


    1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
    Re[9]: VC|++ 2005
    От: MaximE Великобритания  
    Дата: 13.10.05 14:12
    Оценка:
    Здравствуйте, remark, Вы писали:

    []

    ME>>Поиск неквалифицированных имен не ищет объявление. Он ищет первый scope, в котором это имя доступно. scope, в котором имя объявлено, всего лишь один, в которых оно доступно — один и более.


    R>Придётся ещё раз ответить

    R>Не доступно, а видимо. Это принципиальная разница. Если он искал доступное имя, то нашёл бы как раз ::A.

    Здесь "доступно" имелось ввиду на этапе поиска имени, а не на более позднем этапе проверки доступности private/public. Простите за неточность.
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.