namespace
От: Lostar Россия  
Дата: 22.10.02 08:50
Оценка:
Как в пределах каког-то namespace scope-а объявить и определить функцию global namescope?
Почему возникла такая проблема: есть два макроса которые точно будут вставлятся в определение и реализацию нужных классов (аля MFC) в низ определяется operator>>, сейчас он получается определенным внутри какого-то namespace(т.к. эти макросы должны быть прописаны внутри соответ. namespace-а), что очень неудобно т.к. в этом случае нельзя например просто написать:
[ccode]
stream << MyDerivedClass;
[\ccode]
можно конечно перед этим указать using, но как то это не очень
С уважением, Николай.
Re: namespace
От: __Nicolay Россия  
Дата: 22.10.02 08:56
Оценка:
Здравствуйте Lostar, Вы писали:

L>Как в пределах каког-то namespace scope-а объявить и определить функцию global namescope?


namespace a
{
    namespace
    {
        void f1()
        {
        }

    }
}


f1 — в глобальном намеспэйсе
Re: namespace
От: Павел Кузнецов  
Дата: 22.10.02 09:00
Оценка:
Здравствуйте Lostar, Вы писали:

L>Как в пределах каког-то namespace scope-а объявить и определить функцию global namescope?


Закрыть namespace, определить функцию и переоткрыть namespace.

L>Почему возникла такая проблема: есть два макроса которые точно будут вставлятся в определение и реализацию нужных классов (аля MFC) в низ определяется operator>>, сейчас он получается определенным внутри какого-то namespace(т.к. эти макросы должны быть прописаны внутри соответ. namespace-а), что очень неудобно т.к. в этом случае нельзя например просто написать:

L>[ccode]
L>stream << MyDerivedClass;
L>[\ccode]

Если operator << находится в namespace, в котором определен класс MyDerivedClass или один из его базовых классов, то можно. Вот пример вполне корректной программы:

#include <iostream>

namespace n1 {

  class Base { };

  std::ostream& operator <<(std::ostream& os, Base&)
  {
    return os;
  }
}

namespace n2 {

  class Derived : public n1::Base { };
}

int main()
{
  n2::Derived d;
  std::cout << d;
}
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: namespace
От: Павел Кузнецов  
Дата: 22.10.02 09:08
Оценка:
Здравствуйте __Nicolay, Вы писали:

N>
N>namespace a
N>{
N>    namespace
N>    {
N>        void f1()
N>        {
N>        }

N>    }
N>}
N>


N>f1 — в глобальном намеспэйсе


Неверно. f1 находится в анонимном namespace, который, в свою очередь, находится в namespace a. Почти эквивалентно следующему:

namespace a
{
  static void f1()
  {
  }
}
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: namespace
От: __Nicolay Россия  
Дата: 22.10.02 09:12
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

ПК>Неверно.

Виноват, действительно, значит только закрывать — открывать заново.
Re[3]: namespace
От: Алекс Россия http://wise-orm.com
Дата: 22.10.02 09:24
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

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


[]

ПК>Неверно. f1 находится в анонимном namespace, который, в свою очередь, находится в namespace a. Почти эквивалентно следующему:


[]

Почему почти?
Re[4]: namespace
От: Павел Кузнецов  
Дата: 22.10.02 09:34
Оценка:
Здравствуйте Алекс, Вы писали:

ПК>>Неверно. f1 находится в анонимном namespace, который, в свою очередь, находится в namespace a. Почти эквивалентно следующему: <использование static>


А>Почему почти?


В первом случае f1 имеет external linkage. Т.е., например, в первом случае f1 может быть использована в качестве аргумента шаблона, а во втором — нет:

template<void(*f)()>
class C
{
};


namespace {

void f1()
{
}

}

int main()
{
  C<f1> c; // OK
}


static void f1()
{
}

int main()
{
  C<f1> c; // ERROR: f1 должна иметь external linkage
}
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: namespace
От: Алекс Россия http://wise-orm.com
Дата: 22.10.02 09:47
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

ПК>Здравствуйте Алекс, Вы писали:


ПК>>>Неверно. f1 находится в анонимном namespace, который, в свою очередь, находится в namespace a. Почти эквивалентно следующему: <использование static>


А>>Почему почти?


ПК>В первом случае f1 имеет external linkage.


[]

Не совсем понятно.
Я думал анонимные пространства имен нужны для сокрытия глобальных переменных и функций в данном модуле. Из другого модуля к ним нельзя обратиться и, соответственно, там могут быть функции с теми же именами. Static, вроде как, тоже делает доступным функцию только в данном модуле.

Чего такое external linkage?
Re: namespace
От: Аноним  
Дата: 22.10.02 09:49
Оценка:
Здравствуйте Lostar, Вы писали:

L>Как в пределах каког-то namespace scope-а объявить и определить функцию global namescope?

L>Почему возникла такая проблема: есть два макроса которые точно будут вставлятся в определение и реализацию нужных классов (аля MFC) в низ определяется operator>>, сейчас он получается определенным внутри какого-то namespace(т.к. эти макросы должны быть прописаны внутри соответ. namespace-а), что очень неудобно т.к. в этом случае нельзя например просто написать:
L>[ccode]
L>stream << MyDerivedClass;
L>[\ccode]
L>можно конечно перед этим указать using, но как то это не очень

Я, вероятно, покажу свою темноту, но разве MSVC++ не поддерживает поиск имен по-Кенигски для операторов?
Re[2]: namespace
От: Lostar Россия  
Дата: 22.10.02 09:50
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

ПК>Закрыть namespace, определить функцию и переоткрыть namespace.

Была такая мысль ... Проблема в том что в макросе мы не знаем имя namespace-а, его конечно можно ввести в виде отдельного параметра
но это все излишне усложняет

ПК>Если operator << находится в namespace, в котором определен класс MyDerivedClass или один из его базовых классов, то можно. Вот пример вполне корректной программы:


ПК>
ПК>#include <iostream>

ПК>namespace n1 {

ПК>  class Base { };

ПК>  std::ostream& operator <<(std::ostream& os, Base&)
ПК>  {
ПК>    return os;
ПК>  }
ПК>}

ПК>namespace n2 {

ПК>  class Derived : public n1::Base { };
ПК>}

ПК>int main()
ПК>{
ПК>  n2::Derived d;
ПК>  std::cout << d;
ПК>}


Классно!
Походу моя ошибка в том что я использовал оператор НЕ член класса, повидимому из-за этого у меня этот пример не компилялся. так?
С уважением, Николай.
Re[3]: namespace
От: Аноним  
Дата: 22.10.02 09:55
Оценка:
ПК>>namespace n1 {

ПК>> class Base { };


ПК>> std::ostream& operator <<(std::ostream& os, Base&)

ПК>> {
ПК>> return os;
ПК>> }
ПК>>}

ПК>>namespace n2 {


ПК>> class Derived : public n1::Base { };

ПК>>}

ПК>>int main()

ПК>>{
ПК>> n2::Derived d;
ПК>> std::cout << d;
ПК>>}[/c]

L>Классно!

L>Походу моя ошибка в том что я использовал оператор НЕ член класса, повидимому из-за этого у меня этот пример не компилялся. так?

Так в примере у ПК это и есть оператор НЕ член. Типа оператор ищется в пространстве имен базового класса.
Re[2]: namespace
От: Аноним  
Дата: 22.10.02 09:56
Оценка:
А>Я, вероятно, покажу свою темноту, но разве MSVC++ не поддерживает поиск имен по-Кенигски для операторов?

Тут дело непонятное. Для операторов поддерживает, а вот для функций не операторов нет.
Re[3]: namespace
От: Аноним  
Дата: 22.10.02 09:57
Оценка:
Здравствуйте Аноним, Вы писали:

А>Тут дело непонятное. Для операторов поддерживает, а вот для функций не операторов нет.


Но ведь в исходном сообщении был оператор?
Re[4]: namespace
От: Аноним  
Дата: 22.10.02 10:06
Оценка:
А>Но ведь в исходном сообщении был оператор?
Да, оператор.
Re[3]: namespace
От: Lostar Россия  
Дата: 22.10.02 10:11
Оценка:
Здравствуйте Lostar, Вы писали:

L>Классно!

L>Походу моя ошибка в том что я использовал оператор НЕ член класса, повидимому из-за этого у меня этот пример не компилялся. так?
Да точно, я ошибся.

Однако наблюдается интересная ситуация:
Тот пример который дал Павел успешно компилируется. Теперь однако становится совсем неясно почему это не срабатывает в моем случае.
Причем если я явно укажу [ccode]using MyNamespace::operator>>;[\ccode] то мои исходники успешно скомпилируются и все будет ок. Непонятно...
Да кстати компилятор MSVC6.
Если попробовать скомпилировать исходники с помощью интеловского компилятора, то все получается и без [ccode]using[\ccode].
Где грабли?
С уважением, Николай.
Re[4]: namespace
От: Павел Кузнецов  
Дата: 22.10.02 10:16
Оценка:
Здравствуйте Lostar, Вы писали:

L>Тот пример который дал Павел успешно компилируется. Теперь однако становится совсем неясно почему это не срабатывает в моем случае. <...> Где грабли? :)


А где исходник? Редуцируй до приемлемых размеров и давай его сюда — будем разбираться ;-)
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: namespace
От: Lostar Россия  
Дата: 22.10.02 10:29
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

ПК>А где исходник? Редуцируй до приемлемых размеров и давай его сюда — будем разбираться


declares.h
[ccode]
#define DECLARE_REGISTERING(classname) \
...
friend CAStream& operator>>(CAStream& stream, classname * &pOb);\
...

#define IMPLEMENT_REGISTERING(classname, version) \
...
CAStream& operator>>(CAStream& ar, classname* &pOb)\
{ ... \
}
[ccode]

childobject.h
[ccode]
#include "declares.h"

class CAChildObject
{

public:

CAChildObject();
~CAChildObject();

DECLARE_REGISTERING(CAChildObject);
};
[\ccode]

childobject.cpp
[ccode]
#include "childobject.h"

IMPLEMENT_REGISTERING(CAChildObject, 1.0); // имя класса и версия
[\ccode]

Да я вот тут заметил что у нас в хидере стоит friend модификатор, но он вроде не делает declaration для функции и тогда становится понятно почему он не находит этого оператора. Интересно как тогда на это влияет использование using и где находит declaration интеловский компайлер..
С уважением, Николай.
Re[6]: namespace
От: Павел Кузнецов  
Дата: 22.10.02 10:33
Оценка: 17 (3)
Здравствуйте Алекс, Вы писали:

ПК>>>>Неверно. f1 находится в анонимном namespace <...> Почти эквивалентно следующему: <использование static>


А>>>Почему почти?


ПК>>В первом случае f1 имеет external linkage.


А>Я думал анонимные пространства имен нужны для сокрытия глобальных переменных и функций в данном модуле.


Верно. + имена классов и шаблонов

А>Из другого модуля к ним нельзя обратиться и, соответственно, там могут быть функции с теми же именами.


Верно.

А>Static, вроде как, тоже делает доступным функцию только в данном модуле.


Тоже верно.

А>Чего такое external linkage?


Хороший вопрос... Быстро и не ответишь. Если оставить теорию побоку, то, грубо говоря, имена с external linkage в том или ином виде доступны компоновщику, т.е. могут быть использованы для обозначения объектов, ссылок, функций, типов, шаблонов, namespace или значений из других единиц трансляции и/или принимать участие в манглировании других имен (например, имен, порождаемых при инстанциировании шаблонов).

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

Будучи определена в анонимном namespace, функция f1 имеет external linkage. Однако, т.к. для анонимного namespace компилятором сгенерировано уникальное имя, не известное пользователю, объявить ее в другой единице трансляции невозможно. Т.е. в этом отношении эффект такой же как и при использовании static, но достигается другим путем. Разница же состоит в том, что имя этой функции может быть использовано для составления манглированных имен, в частности, при инстанциировании шаблонов.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: namespace
От: Lostar Россия  
Дата: 22.10.02 10:35
Оценка:
Здравствуйте Lostar, Вы писали:

L>Здравствуйте Павел Кузнецов, Вы писали:


ПК>>А где исходник? Редуцируй до приемлемых размеров и давай его сюда — будем разбираться


L>declares.h

L>[ccode]
L>#define DECLARE_REGISTERING(classname) \
L> ...
L> friend CAStream& operator>>(CAStream& stream, classname * &pOb);\
L> ...
L>
L>#define IMPLEMENT_REGISTERING(classname, version) \
L> ...
L> CAStream& operator>>(CAStream& ar, classname* &pOb)\
L> { ... \
L> }
L>[\ccode]

L>childobject.h

L>[ccode]
L>#include "declares.h"

L>class CAChildObject

L>{

L>public:

L>
L> CAChildObject();
L> ~CAChildObject();

L> DECLARE_REGISTERING(CAChildObject);

L>};
L>[\ccode]

L>childobject.cpp

L>[ccode]
L>#include "childobject.h"

L>IMPLEMENT_REGISTERING(CAChildObject, 1.0); // имя класса и версия

L>[\ccode]

L>Да я вот тут заметил что у нас в хидере стоит friend модификатор, но он вроде не делает declaration для функции и тогда становится понятно почему он не находит этого оператора. Интересно как тогда на это влияет использование using и где находит declaration интеловский компайлер..


сорри, забыл написать как собственно говоря используется:

[ccode]
#include "childobject.h"

void main
{
...
CAChildObject *obj = new CAChildObject;
stream << obj;
}
[\ccode]
С уважением, Николай.
Re[7]: namespace
От: Алекс Россия http://wise-orm.com
Дата: 22.10.02 11:04
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

ПК>Здравствуйте Алекс, Вы писали:


[]

Бальшое пасибо.