смысл unnamed namespace
От: Аноним  
Дата: 03.08.06 05:30
Оценка:
попрвьте меня плзз, где я не прав:

пусть у нас есть h-ик типа:

namespace{
  int a;
}


1. к элементам, объевленным в неименованном пр-ве имен, можно получить доступ только в той же единице компиляции.
2. единица компиляции — cpp — ик со всеми включенными в него хидерами.
3. во всех сpp -ах в которые я проиклюдю вышеуказнный хидер, а — будет досупна.
4. куда же не проинклюжу, не будет...

но ведь так же было бы и без безымянного пр-ва имен...

зы пните меня плзз, где я туплю
Re: смысл unnamed namespace
От: valker  
Дата: 03.08.06 05:39
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

А>попрвьте меня плзз, где я не прав:


А>пусть у нас есть h-ик типа:


А>
А>namespace{
А>  int a;
А>}
А>


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

А>2. единица компиляции — cpp — ик со всеми включенными в него хидерами.
А>3. во всех сpp -ах в которые я проиклюдю вышеуказнный хидер, а — будет досупна.
А>4. куда же не проинклюжу, не будет...

А>но ведь так же было бы и без безымянного пр-ва имен...


А>зы пните меня плзз, где я туплю


По-моему, безымянное пространство имён — аналог static для переменных. Т.е. в каждой единице трансляции будет свой "int a;", а без static или namespace будет один на всех, точнее надо в одной единице определить, а в других extern'ом объявить.

IMHO.
Posted using RSDN@HOME
Re[2]: смысл unnamed namespace
От: Аноним  
Дата: 03.08.06 05:53
Оценка:
Здравствуйте, valker, Вы писали:


V>По-моему, безымянное пространство имён — аналог static для переменных. Т.е. в каждой единице трансляции будет свой "int a;", а без static или namespace будет один на всех, точнее надо в одной единице определить, а в других extern'ом объявить.



Спасибо!

А как быть с функциями и классами определенными там же?
Re: смысл unnamed namespace
От: Master Yoda Великобритания  
Дата: 03.08.06 06:37
Оценка: 7 (2)
Здравствуйте, <Аноним>, Вы писали:

А>зы пните меня плзз, где я туплю


Можно посмотреть предыдущие обсуждения про unnamed namespaces:

Двойная защита :)
Автор: _Winnie
Дата: 14.01.06

Неименованные пространства имен
Автор: Feb
Дата: 02.04.04

Неименованные namespace в h &mdash; файле
Автор: Евгений Чечковский
Дата: 04.05.02


Можно почитать о них в MSDN:

Unnamed namespaces

You can declare an unnamed namespace as a superior alternative to the use of global static variable declarations.
namespace { namespace-body }

An unnamed-namespace-definition having the syntax shown above behaves as if it were replaced by:
namespace unique { namespace-body }
using namespace unique;

Each unnamed namespace has an identifier, assigned and maintained by the program and represented here by unique, that differs from all other identifiers in the entire program. For example:
// unnamed_namespaces.cpp
// C2872 expected
namespace { int i; }          // unique::i
void f() { i++; }             // unique::i++

namespace A {
    namespace {
        int i;      // A::unique::i
        int j;      // A::unique::j
    }
}

using namespace A;

void h()
{
    i++;            // C2872: unique::i or A::unique::i
    A::i++;         // C2872: A::i undefined
    j++;            // A::unique::j++
}

Unnamed namespaces are a superior replacement for the static declaration of variables. They allow variables and functions to be visible within an entire translation unit, yet not visible externally. Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.


Можно посмотреть и стандарт:

7.3.1.1 Unnamed namespaces [namespace.unnamed]
1 An unnamed-namespace-definition behaves as if it were replaced by

namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }

where all occurrences of uniquein a translation unit are replaced by the same identifier and this identifier differs from
all other identifiers in the entire program.87) [ Example:
namespace { int i ; } // unique::i
void f () { i ++; } // unique::i++
namespace A {
    namespace {
        int i; // A:: unique ::i
        int j; // A:: unique ::j
    }
    void g () { i ++; } // A:: unique ::i++
}
using namespace A;
void h () {
    i ++; // error: unique ::i or A:: unique ::i
    A::i ++; // A:: unique ::i
    j ++; // A:: unique ::j
}

—end example ]
2 The use of the static keyword is deprecated when declaring objects in a namespace scope (see annex D); the unnamednamespace
provides a superior alternative.


Думаю это даст ответы на часть твоих вопросов
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[2]: смысл unnamed namespace
От: Аноним  
Дата: 03.08.06 07:01
Оценка:
Здравствуйте, Master Yoda, Вы писали:

MY>Думаю это даст ответы на часть твоих вопросов


Спасибо, но я читал...
видно совсем туплю (

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

пусть у меня есть две единицы компиляции с проинклюденным в них одним и тем же h-ом с функцией в безымянном пр-ве имен. Получается у меня будет два независимых экземляра этой функции? нафига?
Re[3]: смысл unnamed namespace
От: Кодт Россия  
Дата: 03.08.06 07:23
Оценка:
Здравствуйте, <Аноним>, Вы писали:

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


Вообще-то, элементы безымянного пространства имеют внешнее связывание. В этом их выгодное отличие от статиков: указатели можно использовать как параметры шаблонов.

А>пусть у меня есть две единицы компиляции с проинклюденным в них одним и тем же h-ом с функцией в безымянном пр-ве имен. Получается у меня будет два независимых экземляра этой функции? нафига?


Например, разные комплекты статических переменных этой функции в каждом .cpp-файле. Пригодится! (Не могу придумать, как именно... но например, для отладки).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: смысл unnamed namespace
От: Cyberax Марс  
Дата: 03.08.06 07:36
Оценка:
Кодт wrote:
> Например, разные комплекты статических переменных этой функции в каждом
> .cpp-файле. Пригодится! (Не могу придумать, как именно... но например,
> для отладки).
Еще безымянные пространства имен используются в качестве защиты от
слишком умного ADL.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[4]: смысл unnamed namespace
От: Аноним  
Дата: 03.08.06 07:41
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вообще-то, элементы безымянного пространства имеют внешнее связывание. В этом их выгодное отличие от статиков: указатели можно использовать как параметры шаблонов.


Все, тогда я совсем в ступоре.
нафига тогда ентот безымянный нужен?
только для объектов, для замены static? ну тогда задача выеденного яйца не стоит.
с функциями получается никакой выгоды нет... с классами то же.
разве если токо использовать быз. пр-во имен в cpp-ах? Ну так их оттуда всеравно видно не будет...

ЗЫ Видно спать надо больше.. а то я тут вторую ночь подряд за компом мозги в ступоре полном ((
но интересно блин оторваться не могу...
Re[5]: смысл unnamed namespace
От: Roman Odaisky Украина  
Дата: 03.08.06 08:36
Оценка:
Здравствуйте, Аноним, Вы писали:

К>>Вообще-то, элементы безымянного пространства имеют внешнее связывание. В этом их выгодное отличие от статиков: указатели можно использовать как параметры шаблонов.


А>Все, тогда я совсем в ступоре.

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

Вот я делал так:

file.h
namespace
{
    __int64 const XYZ_CONST0 = ...;
    __int64 const XYZ_CONST1 = ...;
    __int64 const XYZ_CONST2 = ...;
    __int64 const XYZ_CONST3 = ...;
}

и всё в порядке при линковке, и значения подставляются в асм открытым текстом. Может, есть способы красивее, но этот и так достигает всего, что надо.
До последнего не верил в пирамиду Лебедева.
Re[5]: смысл unnamed namespace
От: Кодт Россия  
Дата: 03.08.06 08:39
Оценка: 2 (1)
Здравствуйте, <Аноним>, Вы писали:

А>Все, тогда я совсем в ступоре.

А>нафига тогда ентот безымянный нужен?

Скажем так: пока он тебе не пригодился — не пользуйся. Делов-то.

А>только для объектов, для замены static? ну тогда задача выеденного яйца не стоит.

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

Вот смотри, где это может аукнуться.
// common.h

template<class T> struct foo
{
    static void run() { T obj; obj.run(); }
};

void run_a();
void run_b();

// a.cpp

struct hello
{
    int x;
    hello() : x(123) {}
    void run() { cout << ++x; }
};

void run_a() { foo<hello>::run(); }

// b.cpp

struct hello
{
    string s;
    hello() : s("hi!") {}
    void run() { cout << s; }
};

void run_b() { foo<hello>::run(); }

// main.cpp

int main() { run_a(); }

Здесь мы коварным образом нарушили ODR: определили локальные по своей сути классы hello.
Поскольку их методы (конструктор, деструктор и run()) инлайновые, то компилятор помечает их как selectany. Если он не захочет их инлайнить (например, в дебаге), то линкер случайным образом их выберет.
Может получиться такая картина:
— main вызывает run_a
— run_a вызывает случайный foo<hello>::run (для helloa или hellob)
— та, в свою очередь,
— — размещает на стеке объект helloa или hellob соответственно (здесь ещё всё в порядке)
— — вызывает случайный конструктор (удар №1 — можем расстрелять стек, поскольку размеры классов не совпадают)
— — вызывает случайный hello::run
— — — тот обращается к данным (удар №2 — например, реинтерпретация int как string)
— — вызывает случайный деструктор (удар №3 — создавали один объект, грухнули другой)

Конечно, в таком простом примере это всё надуманно: достаточно дать классам уникальные имена. А если классы генерируются макросом?

Сделать локальные классы, как приведено ниже?
void run_a()
{
    struct hello
    {
        int x;
        hello() : x(123) {}
        void run() { cout << ++x; }
    };
    
    hello obj; obj.run(); obj.x = 456; // можно
    foo<hello>::run(); // ошибка
}

Вот, кстати, практическое применение — не надуманное.
struct print_element // утилита, нужная только в данном .cpp-файле
{
    string name;
    int i;
    print_element(string s, int start=0) : name(s), i(start) {}
    template<class T> void operator()(const T& value) { cout<<name<<"["<<(i++)<<"] = "<<value<<";"<<endl;
};

void dump_my_data()
{
    vector<int> vec;
    string str;
    .....
    for_each(vec.begin(), vec.end(), print_element("vec")); // for_each<Iter,Func> параметризуется классом print_element
    for_each(str.begin(), str.end(), print_element("str"));
}

Чтобы не рисковать нарушением ODR, положим наши классы hello и print_element в безымянное пространство. И будет щасте!
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.