对命名空间中类内部定义的朋友函数模板的未定义引用

时间:2018-07-30 02:16:01

标签: c++11 linker namespaces c++14 friend-function

这是我对this question的回答。

我发布的原始答案没有任何名称空间,它可以解决问题。但是,OP随后进行了编辑,声称如果类在名称空间中,则该解决方案不起作用。

我最初的反应是,只需在全局范围内或在using N::f;(或任何其他函数)内部使用main(),就可以使其工作。虽然确实是这样,但《 OP》(合理地)评论说这并不理想,我同意。

尽管如此,我仍然认为在没有N::f的情况下调用using N::f; 而没有应该很好,但是令我惊讶的是,当我尝试以下操作时遇到了未定义的引用错误:

#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&)'

在这一点上,我继续尝试不同的编译器版本,发现上面的工作原理与没有namespace with GCC < 6但没有not with GCC > 6的情况相同。 ICC 17似乎也在f内部进行了受保护成员的访问,但没有选择ICC 18Clang永远不会捡起它。

预期的行为是什么?在没有using N::f;的情况下,是否应该使定义可用于链接器?


编辑1:

为明确起见,我想保留预期的行为,即仅将f限制为friend的实例,使其匹配其参数(因此在示例{{1} }将从Classf,而不是friend)。

0 个答案:

没有答案