Неразрешенный внешний символ с перегрузкой оператора и шаблонами - PullRequest
2 голосов
/ 07 августа 2011

При попытке скомпилировать эту программу:

namespace MyNamespace {
    template<typename T>
    class Test {
    public:
        class Inner {
            int x;
            public:
                    Inner() : x(0) { }
            friend Inner& operator++(Inner& rhs);
        };

        Inner i;
    };
}

template<typename T>
typename MyNamespace::Test<T>::Inner& operator++(typename MyNamespace::Test<T>::Inner& rhs) {
    rhs = MyNamespace::Test<T>::Inner(rhs.x + 1);

    return rhs;
}

int main() {
    MyNamespace::Test<int> t;
    MyNamespace::Test<int>::Inner i = t.i;
    ++i;
}

Я получаю ошибку

неразрешенный внешний символ "class MyNamespace :: Test :: Inner & __cdecl MyNamespace :: operator ++(класс MyNamespace :: Test :: Inner &) "(?? EMyNamespace @@ YAAAVInner @? $ Test @ H @ 0 @ AAV120 @@ Z), на который ссылается функция _main

Что странно, потому чтоэто точная сигнатура функции-друга operator++, которую я определил.Как это исправить?И у меня нет возможности включить в качестве функции-члена, потому что мне нужно изменить объект, на который ссылается операнд, без использования конструктора копирования (потому что нет конструктора копирования).

Обновление:

Если я добавлю template<typename T> выше friend Inner&..., я получу ошибки

could not deduce template argument for 'T' 1>         
main.cpp(21) : see declaration of 'operator
++' 
error C2783:
'MyNamespace::Test<T>::Inner &MyNamespace::operator++(MyNamespace::Test<T>::Inner &)' : could not deduce template
argument for 'T' with
[
              T=int
]          
main.cpp(13) : see declaration of
'MyNamespace::operator ++' 
main.cpp(30): error C2675: unary '++' : 'MyNamespace::Test<T>::Inner' does not define this operator or a
conversion to a type acceptable to the predefined operator

with
[
              T=int
]

1 Ответ

3 голосов
/ 07 августа 2011

Почему вы думаете, что это не может быть функцией-членом?Элемент экземпляра должен работать просто отлично:

namespace MyNamespace
{
    template<typename T>
    class Test
    {
    public:
        class Inner
        {
            int x;
        public:
            Inner& operator++( void ) { ++x; return *this; }
        };

        Inner i;
    };
}

Для этого не требуется конструктор копирования.

Определение друга также должно работать, если определение выполняется с помощью объявления друга:

namespace MyNamespace
{
    template<typename T>
    class Test
    {
    public:
        class Inner
        {
            int x;
        public:
            friend Inner& operator++( Inner& operand ) { ++operand.x; return operand; }
        };

        Inner i;
    };
}

Функция Friend будет размещена в области имен, в соответствии с [class.friend]

...