Друзья, ключевое слово оператора и разрешение области

namespace GameForge
{
    namespace Core
    {
        class CTribool;
    }
}

GameForge::Core::CTribool operator ! ( const GameForge::Core::CTribool& rkTribool );

namespace GameForge
{
    namespace Core
    {
        class CTribool
        {
            friend CTribool operator ! ( const CTribool& rkTribool );

        private:
            EState m_eState;
        };
    }
}


GameForge::Core::CTribool operator ! ( const GameForge::Core::CTribool& rkTribool )
{
    switch( rkTribool.m_eState )
        {
    // Some stuff...

Не компилируется, так как m_eState недоступен в последнем определении. Причина в том, что объявление друга происходит в пространстве имен CTribool и, таким образом, объявляет другую функцию. Поэтому я попытался использовать оператор разрешения области следующим образом.

friend CTribool ::operator ! ( const CTribool& rkTribool );

а также

friend CTribool ::( operator ! ) ( const CTribool& rkTribool );

Но это тоже не работает, потому что каким-то образом CTribool не распознается как допустимый тип. Я подозреваю, что форвардного объявления в этом случае недостаточно. Любая работа вокруг?


person Adrian Goudard    schedule 22.06.2013    source источник
comment
Дело не в том, что CTribool не распознается как допустимый тип. Когда вы используете полное имя в объявлении friend, вы должны ссылаться на то, что уже объявлено.   -  person Angew is no longer proud of SO    schedule 22.06.2013
comment
Есть ли способ добиться того, что я пытаюсь сделать? Я имею в виду, что тогда есть какая-то круговая зависимость ( операторы CTribool -> CTribool -> дружба с операторами ).   -  person Adrian Goudard    schedule 22.06.2013
comment
Не используйте C в качестве префикса для классов, это никогда не было уместно и было основано исключительно на непонимании соглашений об именах MFC.   -  person Konrad Rudolph    schedule 22.06.2013


Ответы (2)


Как ни странно, вам нужно сделать это:

        friend CTribool (::operator !) ( const CTribool& rkTribool );

Вам нужно указать, что ваша функция находится в глобальной области видимости, но без круглых скобок ваш :: будет связан с CTribool, как если бы вы делали это:

        friend (CTribool::operator !) ( const CTribool& rkTribool );

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

person Vaughn Cato    schedule 22.06.2013

Вы должны определить свой оператор в том же пространстве имен, что и класс CTribool. Это правильный способ сделать это; он будет найден во время применения с помощью ADL:

namespace GameForge
{
    namespace Core
    {
        class CTribool
        {
            friend CTribool operator ! ( const CTribool& rkTribool );

        private:
            EState m_eState;
        };
    }
}



namespace GameForge
{
    namespace Core
    {
        CTribool operator ! ( const GameForge::Core::CTribool& rkTribool )
        {
            switch( rkTribool.m_eState )
                {
                // Some stuff...
                }
        }
    }
}
person Angew is no longer proud of SO    schedule 22.06.2013