未解决的外部符号与运算符重载和模板

时间:2011-08-07 17:08:11

标签: c++ templates operator-overloading linker-errors

在尝试编译此程序时:

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;
}

我收到错误

  

未解析的外部符号“类MyNamespace :: Test :: Inner&amp; __cdecl MyNamespace :: operator ++(class MyNamespace :: Test :: Inner&amp;)”(?? 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 个答案:

答案 0 :(得分:3)

为什么你认为它不能成为会员功能?实例成员应该可以正常工作:

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;
    };
}

根据[class.friend]

,友元函数将被放置在命名空间范围内