Undefined reference to friend function template defined inside class in a namespace

我的梦境 提交于 2019-12-07 18:24:35

问题


This is a follow-up on my answer to this question.

The original answer I posted does not have any namespaces, and it solves the problem. However, the OP subsequently made an edit claiming that the solution does not work if the class is inside a namespace.

My initial reaction was that you can make it work by simply having using N::f; either at global scope or inside main() (or any other function). While that is certainly the case, the OP (justifiably) commented that this is not ideal, and I agree.

Nevertheless, I still thought that calling N::f without having using N::f; should work just fine, but to my surprise I got an undefined reference error when I tried the following:

#include<iostream>

namespace N
{
    template<class T>
    class Class;

    template<typename U, typename W>
    Class<W> f (Class<U>& C, const Class<U>& D);

    template<class T>
    class Class
    {

    protected: // this could be private

        T m_t;

    public:
        Class()
            :
              m_t(T())
        {}

        Class(T t)
            :
              m_t(t)
        {}

        T& getT()
        {
            return m_t;
        }

        template<typename U, typename W>
        friend Class<W> f (Class<T>& C, const Class<T>& D)
        {
            C.m_t += D.m_t;
            Class<W> R;
            std::cout << R.m_t << std::endl; // I don't want this to be possible
            return R;
        }
    };
}

int main()
{
    N::Class<int> C(42), D(24);
    std::cout << N::f<int, char>(C, D).getT() << std::endl;
}

error: undefined reference to N::Class<char> N::f<int, char>(N::Class<int>&, N::Class<int> const&)'.

At this point, I went on to try different compiler versions and discovered that the above works as it does without a namespace with GCC < 6 but not with GCC > 6. ICC 17 also seems to pick up on the protected member access inside f, but not ICC 18. Clang never picks it up.

Which is the intended behaviour? Should the definition be made available to the linker in this case without using N::f;?.


Edit 1:

To clarify, I want to retain the intended behaviour, namely restricting f to be a friend only to Class instantiations that match its arguments (so in the example f would be friend to Class<T> but not to Class<W>).

来源:https://stackoverflow.com/questions/51586190/undefined-reference-to-friend-function-template-defined-inside-class-in-a-namesp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!