【问题标题】:Why doesn't that template function compile?为什么该模板函数不编译?
【发布时间】:2012-09-07 02:28:27
【问题描述】:

这是一个非常短的 sn-p,它不能用 g++ 4.7.1 编译(顺便说一下,它也不能用 gcc 4.6.3 编译)。

#include <iostream>

template<typename T>
struct Foo
{
    template<typename U>
    friend std::ostream& operator<<(Foo&, U&);
};

template<typename T, typename U>
std::ostream& operator<<(Foo<T> foo, U& u)
{
    std::cout << u;
    return std::cout;
}

int main()
{
    Foo<int> f;
    f << "bar";
    return 0;
}

这就是 gcc 4.7.1 的输出(4.6.3 说的几乎相同)。

/tmp/ccNWJW6X.o: 在函数main': main.cpp:(.text+0x15): undefined reference tostd::basic_ostream >& 运算符

谁能解释一下原因?

编辑

我也尝试过使用 clang 3.1,它说的完全一样。

【问题讨论】:

    标签: c++ templates gcc linker template-function


    【解决方案1】:

    与模板的关系可能有点复杂......让我们看看你的代码做了什么:

    template<typename T>
    struct Foo {
        template<typename U>
        friend std::ostream& operator<<(Foo&, U&);  // [1]
    };
    template<typename T, typename U>
    std::ostream& operator<<(Foo<T> foo, U& u) {    // [2]
        std::cout << u;
        return std::cout;
    }
    

    当您使用类型实例化Foo 时,例如int,[1] 中的朋友声明声明了一个模板函数:

    template <typename U>
    std::ostream& operator<<(Foo<int>&,U&);
    

    但是该函数在任何地方都不存在,您在 [2] 中提供的是一个带有两个参数的模板:

    template<typename T, typename U>
    std::ostream& operator<<(Foo<T> foo, U& u);
    

    关键是在模板实例化的同时处理友元声明,此时Foo代表当前实例化得到的类型。

    您想要做的事情有不同的选择,最简单的是将朋友声明更改为:

    template<typename W, typename U>
    friend std::ostream& operator<<(Foo<W> foo, U& u);
    

    它声明了一个带有两个参数的模板(WU 在此处未绑定),并在命名空间级别匹配您的定义。

    另一个选项是在类模板定义中定义友元函数,在这种情况下,您可以保留原始签名。有关不同替代方案的更多信息,请查看其他 answer

    【讨论】:

      【解决方案2】:

      您实际上并没有为 Foo 编写输出运算符

      请注意,这两个函数的签名非常不同

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-07
        • 1970-01-01
        相关资源
        最近更新 更多