Как подружиться с классом шаблона в родительском пространстве имен?

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

Вот мои попытки и их ошибки с MSVC8 (Visual Studio 2005):


namespace a {
namespace b {

    template<typename T>
    class x;

    namespace c {

        class y
        {
            template<typename T>
            friend class x;
            ...
        };

    }
}}

ошибка C2888: a::b::x: символ не может быть определен в пространстве имен c


namespace a {
namespace b {

    template<typename T>
    class x;

    namespace c {

        class y
        {
            template<typename T>
            friend class ::a::b::x;
            ...
        };

    }
}}

ошибка C2888: a::b::x: символ не может быть определен в пространстве имен c


namespace a {
namespace b {

    namespace c {

        class y
        {
            template<typename T>
            friend class ::a::b::x;
            ...
        };

    }
}}

ошибка C2039: x : не является членом a::b


Я не могу просто включить заголовочный файл, содержащий class x, поскольку он зависит от class y, что приводит к циклическому включению.


person thehouse    schedule 22.05.2012    source источник
comment
У меня работает, должно быть компилятор тупой.   -  person Seth Carnegie    schedule 22.05.2012
comment
Отлично работает с clang 3.1, g++ 4.6.2 и VS 2008. Можете ли вы попробовать скомпилировать тестовую программу, которую @SethCarnegie опубликовал в своей ссылке с MS VS 2005? Похоже на ошибку в компиляторе...   -  person dirkgently    schedule 22.05.2012
comment
Тестовая программа @SethCarnegie дает мне error C2888: 'a::b::x' : symbol cannot be defined within namespace 'c' не идеал. Это даже не сработает, если я полностью определю class x, а не просто объявлю его.   -  person thehouse    schedule 22.05.2012
comment
@thehouse вы думали об обновлении своего компилятора?   -  person Seth Carnegie    schedule 22.05.2012
comment
@SethCarnegie: Я бы сделал это, если бы мог. Это последняя версия, которая (случайно намеренно) не препятствует запуску вашего бинарного файла в старых версиях Windows. Однажды мы надеемся использовать GCC в MinGW, но не сегодня.   -  person thehouse    schedule 22.05.2012
comment
@thehouse вам придется найти какое-то обходное решение, попробуйте создать класс без шаблона или, может быть, функцию без шаблона или что-то в этом роде, и пусть класс шаблона будет работать через эту функцию.   -  person Seth Carnegie    schedule 22.05.2012
comment
@SethCarnegie: Поскольку мне посчастливилось знать все вероятные экземпляры моего template<typename> class x, я взломал его, подружившись с каждым отдельно (см. мой ответ).   -  person thehouse    schedule 22.05.2012


Ответы (1)


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

namespace a {
namespace b {

    template<typename T>
    class x;

    namespace c {

        class y
        {
            friend class x<char>;
            friend class x<wchar_t>;
            ...
        };

    }
}}
person thehouse    schedule 22.05.2012