Как в пределах каког-то namespace scope-а объявить и определить функцию global namescope?
Почему возникла такая проблема: есть два макроса которые точно будут вставлятся в определение и реализацию нужных классов (аля MFC) в низ определяется operator>>, сейчас он получается определенным внутри какого-то namespace(т.к. эти макросы должны быть прописаны внутри соответ. namespace-а), что очень неудобно т.к. в этом случае нельзя например просто написать:
[ccode]
stream << MyDerivedClass;
[\ccode]
можно конечно перед этим указать using, но как то это не очень
Здравствуйте 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;
}
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Алекс, Вы писали:
ПК>>Неверно. 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
}
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Здравствуйте Алекс, Вы писали:
ПК>>>Неверно. 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++ не поддерживает поиск имен по-Кенигски для операторов?
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Закрыть namespace, определить функцию и переоткрыть namespace.
Была такая мысль ... Проблема в том что в макросе мы не знаем имя namespace-а, его конечно можно ввести в виде отдельного параметра
но это все излишне усложняет
ПК>Если operator << находится в namespace, в котором определен класс MyDerivedClass или один из его базовых классов, то можно. Вот пример вполне корректной программы:
ПК>
Классно!
Походу моя ошибка в том что я использовал оператор НЕ член класса, повидимому из-за этого у меня этот пример не компилялся. так?
С уважением, Николай.
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
Оценка:
А>Но ведь в исходном сообщении был оператор?
Да, оператор.
Здравствуйте Lostar, Вы писали:
L>Классно! L>Походу моя ошибка в том что я использовал оператор НЕ член класса, повидимому из-за этого у меня этот пример не компилялся. так?
Да точно, я ошибся.
Однако наблюдается интересная ситуация:
Тот пример который дал Павел успешно компилируется. Теперь однако становится совсем неясно почему это не срабатывает в моем случае.
Причем если я явно укажу [ccode]using MyNamespace::operator>>;[\ccode] то мои исходники успешно скомпилируются и все будет ок. Непонятно...
Да кстати компилятор MSVC6.
Если попробовать скомпилировать исходники с помощью интеловского компилятора, то все получается и без [ccode]using[\ccode].
Где грабли?
Здравствуйте Lostar, Вы писали:
L>Тот пример который дал Павел успешно компилируется. Теперь однако становится совсем неясно почему это не срабатывает в моем случае. <...> Где грабли? :)
А где исходник? Редуцируй до приемлемых размеров и давай его сюда — будем разбираться ;-)
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
IMPLEMENT_REGISTERING(CAChildObject, 1.0); // имя класса и версия
[\ccode]
Да я вот тут заметил что у нас в хидере стоит friend модификатор, но он вроде не делает declaration для функции и тогда становится понятно почему он не находит этого оператора. Интересно как тогда на это влияет использование using и где находит declaration интеловский компайлер..
Здравствуйте Алекс, Вы писали:
ПК>>>>Неверно. f1 находится в анонимном namespace <...> Почти эквивалентно следующему: <использование static>
А>>>Почему почти?
ПК>>В первом случае f1 имеет external linkage.
А>Я думал анонимные пространства имен нужны для сокрытия глобальных переменных и функций в данном модуле.
Верно. + имена классов и шаблонов
А>Из другого модуля к ним нельзя обратиться и, соответственно, там могут быть функции с теми же именами.
Верно.
А>Static, вроде как, тоже делает доступным функцию только в данном модуле.
Тоже верно.
А>Чего такое external linkage?
Хороший вопрос... Быстро и не ответишь. Если оставить теорию побоку, то, грубо говоря, имена с external linkage в том или ином виде доступны компоновщику, т.е. могут быть использованы для обозначения объектов, ссылок, функций, типов, шаблонов, namespace или значений из других единиц трансляции и/или принимать участие в манглировании других имен (например, имен, порождаемых при инстанциировании шаблонов).
Возвращаясь к нашему примеру, функция f1, будучи объявлена как static, имеет internal linkage. Это означает, что это же имя не может быть использовано в другой единице трансляции для обозначения этой же функции и, кроме того, имя этой функции не может быть использовано для составления манглированных имен, например, при инстанциировании шаблонов.
Будучи определена в анонимном namespace, функция f1 имеет external linkage. Однако, т.к. для анонимного namespace компилятором сгенерировано уникальное имя, не известное пользователю, объявить ее в другой единице трансляции невозможно. Т.е. в этом отношении эффект такой же как и при использовании static, но достигается другим путем. Разница же состоит в том, что имя этой функции может быть использовано для составления манглированных имен, в частности, при инстанциировании шаблонов.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте 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]