Здравствуйте, Andrew S, Вы писали:
AS>Всем привет. AS>Есть следующий код:
AS>
AS>// настройка связей, в конфиге, в зависимости от платформы.
AS>namespace fw
AS>{
AS> namespace win
AS> {
AS> }
AS> using namespace win;
AS>}
AS>// реализация
AS>namespace fw
AS>{
AS> namespace win
AS> {
AS> namespace io
AS> {
AS> struct io_impl
AS> {
AS> };
AS> }
AS> }
AS>}
AS>// то, что видит пользователь
AS>namespace fw
AS>{
AS> namespace io
AS> {
AS> // using namespace fw::win::io
AS> struct io_front: io_impl // ошибка компиляции
AS> {
AS> };
AS> }
AS>}
AS>
AS>Для чего это нужно — есть кроссплатформенный фреймворк, реализация для каждой платформы располагается в неймспейсе этой платформы. В зависимости от опций компиляции "морда" собирает это дело при помощи using директив в неймспейс интерфейса фремворка. Сейчас, кроме настройки, которая происходит автоматически, если есть вложенные "ниже" неймспейсы, приходится делать дополнительный using в интерфейсе с пользователем. Не сложно, но и не камильфо.
AS>Что хочется. AS>1. Понять причину ошибки компиляции, в смысле, где в стандарте посмотреть (3.4.6 и 7.3 просмотрел, вроде ничего похожего).
fw::win::io и fw::io это разные namespaces.
7.3.1/3
The original-namespace-name in an extension-namespace-definition shall have previously been defined in
an original-namespace-definition in the same declarative region.
7.3.4/1
A using-directive does not add any members to the declarative region in which it appears.
AS>1 Добиться эффекта, чтобы fw::io мержилось с fw::io(from win) без дополнительного using.
Без дополнительного никак, но его можно вынести как-нибудь так:
Здравствуйте, Andrew S, Вы писали:
AS>Что хочется. AS>1. Понять причину ошибки компиляции, в смысле, где в стандарте посмотреть (3.4.6 и 7.3 просмотрел, вроде ничего похожего). AS>1 Добиться эффекта, чтобы fw::io мержилось с fw::io(from win) без дополнительного using. AS>2. Возможно, есть способ как то порефакторить это, дабы избежать подобных или других проблем. Например, есть мысли неймспейсы реализации расположить в другом порядке: fw::io::win. Как в этом случае обеспечить автоматические линки неймспейсов, не очень понятно (делать include внутри неймспейсов как то некошерно, хотя в данном случае... не знаю, в общем, не по фен шую).
Я так понял, твой вопрос на счет ошибки следующий: есть класс io_impl, определенный в fw::win::io, в самом fw есть using namespace win, который позволяет использовать имена, в том числе io_impl, из fw::win::io так, как будто они в fw::io. А именно, следующий код не вызовет ошибки:
Однако, если попытаться использовать теперь этот факт в стиле:
namespace fw {
namespace io {
class B: public A {} // error
}
}
то компилятор даст ошибку. Твой вопрос: почему. Дело в том, что namespace работают по следующему принципу: когда ты указываешь fw::io::A, то компилятор смотрит, есть ли элемент io внутри fw -- нет, а внутри namespace-ов, которые объявлены как using внутри fw -- есть, а именно внутри debug (или release) есть namespace io, значит используем его, далее, есть ли там класс A -- да. Теперь, допустим, что ты добавил те строчки, что ниже. Ты ОПРЕДЕЛИЛ namespace io внутри fw, теперь, когда копилятор встречает запись fw::io, он смотрит, есть ли io внутри fw -- да, значит это оно и есть (и теперь fw::io никакого отношения к fw::win::io не имеет, т.к. io найдено внутри fw), и далее -- есть ли class A внутри namespace io? -- нет!
Более того, чтобы убить работоспособность первого кода достаточно внутрь namespace fw добавить просто namespace io {} и все! Теперь строчки fw::io::A будут интерпретироваться как fw::io, а не как fw::debug::io или fw::release::io, а там класса A нет -- не скомпилируется.
Вот простой пример, который демонстрирует то, как понимаются имена внутри:
#include <iostream>
namespace A {
char ch = 'A';
}
namespace B {
char ch = 'B';
char ch2 = '2';
}
namespace C {
using namespace A;
}
namespace D {
using namespace A;
using namespace B;
}
namespace E {
using namespace A;
using namespace B;
char ch = 'E';
}
void main(void) {
std::cout << C::ch << std::endl; // A
// std::cout << D::ch << std::endl; // error!
// std::cout << D::A::ch << std::endl; // error!
std::cout << D::ch2 << std::endl; // 2
B::ch2 = '3';
std::cout << D::ch2 << std::endl; // 3
std::cout << E::ch << std::endl; // E
// std::cout << E::A::ch << std::endl; // error!
std::cout << E::ch2 << std::endl; // 3
}
// настройка связей, в конфиге, в зависимости от платформы.namespace fw
{
namespace win
{
}
using namespace win;
}
// реализацияnamespace fw
{
namespace win
{
namespace io
{
struct io_impl
{
};
}
}
}
// то, что видит пользовательnamespace fw
{
namespace io
{
// using namespace fw::win::iostruct io_front: io_impl // ошибка компиляции
{
};
}
}
Для чего это нужно — есть кроссплатформенный фреймворк, реализация для каждой платформы располагается в неймспейсе этой платформы. В зависимости от опций компиляции "морда" собирает это дело при помощи using директив в неймспейс интерфейса фремворка. Сейчас, кроме настройки, которая происходит автоматически, если есть вложенные "ниже" неймспейсы, приходится делать дополнительный using в интерфейсе с пользователем. Не сложно, но и не камильфо.
Что хочется.
1. Понять причину ошибки компиляции, в смысле, где в стандарте посмотреть (3.4.6 и 7.3 просмотрел, вроде ничего похожего).
1 Добиться эффекта, чтобы fw::io мержилось с fw::io(from win) без дополнительного using.
2. Возможно, есть способ как то порефакторить это, дабы избежать подобных или других проблем. Например, есть мысли неймспейсы реализации расположить в другом порядке: fw::io::win. Как в этом случае обеспечить автоматические линки неймспейсов, не очень понятно (делать include внутри неймспейсов как то некошерно, хотя в данном случае... не знаю, в общем, не по фен шую).
AS>// реализация AS>namespace fw AS>{ AS> namespace win AS> { AS> namespace io AS> { AS> struct io_impl AS> { AS> }; AS> } AS> } AS>}
AS>// то, что видит пользователь
AS>namespace fw AS>{ AS> namespace io AS> { AS> // using namespace fw::win::io AS> struct io_front: io_impl // ошибка компиляции AS> { AS> }; AS> } AS>} AS>[/ccode]
Если я правильно понял (в чем я не до конца уверен), то есть два файла. В одном прописаны три пространства имен — fw, внутри которого win, и внутри которого io. Есть второй файл, в котором внутри fw прописан io. В таком случае ничего удивительного, что io_front из fw:win:io не виден в fw:io — это же совершенно другой неймспейс. Было бы как раз очень неправильно, если бы он был виден!
AS>1. Понять причину ошибки компиляции, в смысле, где в стандарте посмотреть (3.4.6 и 7.3 просмотрел, вроде ничего похожего).
Надеюсь, на этот вопрос я ответил.
AS>1 Добиться эффекта, чтобы fw::io мержилось с fw::io(from win) без дополнительного using.
Невозможно, если я все правильно понял.
AS>2. Возможно, есть способ как то порефакторить это, дабы избежать подобных или других проблем.
А почему не классическое решение?
class io {...};
clas win_io : io {...};
class nix_io : io {...};
Здравствуйте, Andrew S, Вы писали:
AS>неймспейсы реализации расположить в другом порядке: fw::io::win. Как в этом случае обеспечить автоматические линки неймспейсов, не очень понятно (делать include внутри неймспейсов как то некошерно, хотя в данном случае... не знаю, в общем, не по фен шую).
Можно делать namespace io_win, например, или ещё какой. А потом задавать для него другое имя что-то типа:
namespace my {
namespace win {
namespace io {
// тут реализация
}
}
namespace io = win::io;
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
V>Если я правильно понял (в чем я не до конца уверен), то есть два файла. В одном прописаны три пространства имен — fw, внутри которого win, и внутри которого io. Есть второй файл, в котором внутри fw прописан io. В таком случае ничего удивительного, что io_front из fw:win:io не виден в fw:io — это же совершенно другой неймспейс. Было бы как раз очень неправильно, если бы он был виден!
Не так.
Выше мы настроили, что все, что из win попадает в fw. Почему то для сущностей в win, получается, это работает.
Более того, если мы закомментим то, что видит пользователь, то вполне сможем использовать fw::io::io_impl. Т.е. с точки зрения меня, как клиента неймспейса fw, получается два (!!!!) вложенных в него неймспейса io, причем разных. Один это внесенный в область видимости из win, а второй нативный. Аргументы "за" такое поведение при лукапе я тоже могу привести, но тем не менее, в данном случае ситуация не очень логична.
AS>>1. Понять причину ошибки компиляции, в смысле, где в стандарте посмотреть (3.4.6 и 7.3 просмотрел, вроде ничего похожего). V>Надеюсь, на этот вопрос я ответил.
Никоим образом.
AS>>1 Добиться эффекта, чтобы fw::io мержилось с fw::io(from win) без дополнительного using. V>Невозможно, если я все правильно понял.
AS>>2. Возможно, есть способ как то порефакторить это, дабы избежать подобных или других проблем. V>А почему не классическое решение? V>class io {...}; V>clas win_io : io {...}; V>class nix_io : io {...};
V>class user_io : win_io
V>Или я чего-то кардинально недопонял?
Видимо, да. Все наоборот. Есть реализации (в неймспейсах платформы), и их наследует или использует конечный класс, который и будет пользовать клиент.
AS>>неймспейсы реализации расположить в другом порядке: fw::io::win. Как в этом случае обеспечить автоматические линки неймспейсов, не очень понятно (делать include внутри неймспейсов как то некошерно, хотя в данном случае... не знаю, в общем, не по фен шую).
E>Можно делать namespace io_win, например, или ещё какой. А потом задавать для него другое имя что-то типа: E>
Не уверен, что я понял мысль. Зачем нам делать это? В чем поинт? Как это использовать для достижения указанной цели (авто инжекта неймспейса в зависимости от конфига)? То, что есть io, я на этапе конфига не знаю — разработчик фреймворка может реализации в неймспейсных кластерах определять, если считает нужным.. io просто в качестве примера иллюстрации проблемы .
Повторюсь. В той схеме, что привел я — не нужно вообще ничего линковать _явно_, правила линка неймспейсов определяются в конфигурации, тот, кто пишет реализации, даже про них не знает. Если не пользует дополнительных неймспейсов Вот это, собственно, и надо как-то раскрутить. Один вариант решения этой проблемы я знаю, и написал о нем — меня он не устраивает.
Здравствуйте, Andrew S, Вы писали:
AS>Повторюсь. В той схеме, что привел я — не нужно вообще ничего линковать _явно_, правила линка неймспейсов определяются в конфигурации, тот, кто пишет реализации, даже про них не знает. Если не пользует дополнительных неймспейсов Вот это, собственно, и надо как-то раскрутить. Один вариант решения этой проблемы я знаю, и написал о нем — меня он не устраивает.
Я так понял, что ты хочешь написать несколько реализаций библиотеки, а в конфигурилке что-то такое определить, что бы само собой оказались вытащенными в самый внешний нэймспаэс нужные из реализаций?
Ну вот если я верно тебя понял, то я и предлагаю тебе написать в win специфичное для win, потом, в конфигурилке можно сделать другое имя для win (скажем current_OS_spec), и разработчик win::io, unix::io, mac::io сможет написать где-то:
namespace io = current_OS_spec::io;
namespace win {
namespace io {
// тут то, что специфично для win::io
}
}
namespace io {
using cur_OS_spec::io; // подняли специфичную часть в io
// тут неспецифичная часть.
}
Другой путь -- в неспецифичной части явно юзать cur_OS_spec::io, а пользователя избавить от такой нужды, подняв нужные для него идентификаторы во внешний io...
Как-то так.
Правда я пока так и не уверен, что понял, что тебе на самом деле надо?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
AS>>Повторюсь. В той схеме, что привел я — не нужно вообще ничего линковать _явно_, правила линка неймспейсов определяются в конфигурации, тот, кто пишет реализации, даже про них не знает. Если не пользует дополнительных неймспейсов Вот это, собственно, и надо как-то раскрутить. Один вариант решения этой проблемы я знаю, и написал о нем — меня он не устраивает.
E>Я так понял, что ты хочешь написать несколько реализаций библиотеки, а в конфигурилке что-то такое определить, что бы само собой оказались вытащенными в самый внешний нэймспаэс нужные из реализаций?
E>Ну вот если я верно тебя понял, то я и предлагаю тебе написать в win специфичное для win, потом, в конфигурилке можно сделать другое имя для win (скажем current_OS_spec), и разработчик win::io, unix::io, mac::io сможет написать где-то: E>namespace io = current_OS_spec::io;
Нет, как раз я про другое. Разработчик специфичной реализации спокойно обитает в неймспейсе своей платформы. Там как раз проблем нет.
Надо то, что он сделает в неймспейсе свой платформы потом вытащить в общий неймспейс. Вот тут и начинаются проблемы.
E>А можно и так:
namespace win {
E> namespace io {
E> // тут то, что специфично для win::io
E> }
E>}
E>namespace io {
E> using cur_OS_spec::io; // подняли специфичную часть в io
E> // тут неспецифичная часть.
E>}
E>
E>Другой путь -- в неспецифичной части явно юзать cur_OS_spec::io, а пользователя избавить от такой нужды, подняв нужные для него идентификаторы во внешний io...
Ну примерно так сеейчас и сделано.. Но ведь криво же...
Здравствуйте, Andrew S, Вы писали:
E>>Другой путь -- в неспецифичной части явно юзать cur_OS_spec::io, а пользователя избавить от такой нужды, подняв нужные для него идентификаторы во внешний io...
AS>Ну примерно так сеейчас и сделано.. Но ведь криво же...
Почему криво? Хотя мне первый путь больше нравится, чем второй, так как разработчик платформы сам решает какие потроха публиковать, а какие нет...
Да и пользователь знает, что может отвалится на другой платформе, а что нет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Andrew S, Вы писали:
E>>>Другой путь -- в неспецифичной части явно юзать cur_OS_spec::io, а пользователя избавить от такой нужды, подняв нужные для него идентификаторы во внешний io...
AS>>Ну примерно так сеейчас и сделано.. Но ведь криво же...
E>Почему криво? Хотя мне первый путь больше нравится, чем второй, так как разработчик платформы сам решает какие потроха публиковать, а какие нет...
E>Да и пользователь знает, что может отвалится на другой платформе, а что нет...
Ну так оно сейчас так примерно и выглядит. Хотелось чтобы линковалось "само". Видимо, не получится. Ок, спасибо за ответы.