模板友好功能和返回类型扣除

时间:2015-01-14 15:29:49

标签: c++ templates friend c++14 return-type-deduction

注意:这个问题非常接近Return type deduction for in-class friend functions,但我没有找到问题的答案。

使用std = c ++ 1y和clang 3.5与std = c ++ 14和std = c ++ 1z进行测试

此代码编译:

#include <iostream>

template<class T>
class MyClass {
    public:
        MyClass(T const& a) : impl(a) {}

        template<class T0, class T1> friend auto
        // requires operator+(T0,T1) exists
        operator+(MyClass<T0> const& a, MyClass<T1> const& b)
        {
            return MyClass<decltype(a.impl+b.impl)>{a.impl + b.impl};
        }

        T getImpl() const { return impl; }

    private:
        T impl;
};

int main() {
    MyClass<int> x(2);
    MyClass<long> y(2);

    auto z = x+y;
    std::cout << z.getImpl() << "\n";
}

现在如果我在类之外定义operator +,它就不再编译了:

template<class T>
class MyClass {
    public:
        MyClass(T const& a) : impl(a) {}

        template<class T0, class T1> friend auto
        operator+(MyClass<T0> const& a, MyClass<T1> const& b);

        T getImpl() const { return impl; }
    private:
        T impl;
};

template<class T0, class T1> auto
operator+(MyClass<T0> const& a, MyClass<T1> const& b)
{
    return MyClass<decltype(a.impl+b.impl)>{a.impl + b.impl};
}

Clang 3.4说:

error: use of overloaded operator '+' is ambiguous (with operand types MyClass<int> and MyClass<long>)

然后指出它认为是两个不同的函数:类中的声明和类外的定义。

我的问题是:它是一个铿锵的错误,还是仅仅为朋友函数推导出模板参数,从而导致两个函数不相等是某些情况? 你会建议什么样的选择:make operator +一个成员函数,或者在类中定义friend operator +(在我看来会混淆类接口)?

仅仅为了您的信息,我有一个这样的代码的实际用例,我尝试包装第三方矩阵类,我需要返回类型推导,因为使用表达式模板进行延迟评估。

编辑:以下工作正常(但仍然使界面混乱......)

template<typename T>
class MyClass
{
    T impl;

public:
    explicit MyClass(T a) : impl(std::move(a)) { }

    T const& getImpl() const { return impl; }

    template<typename T0, typename T1>
    friend auto operator +(MyClass<T0> const& a, MyClass<T1> const& b) -> MyClass<decltype(a.impl + b.impl)>;
};

template<typename T0, typename T1>
auto operator +(MyClass<T0> const& a, MyClass<T1> const& b) -> MyClass<decltype(a.impl + b.impl)>
{
    return MyClass<decltype(a.impl + b.impl)>(a.impl + b.impl);
}

1 个答案:

答案 0 :(得分:1)

编辑: 看一下评论部分,这是gcc 4.8.2和4.9

中的一个错误

Gcc错误代码:

  

prog.cpp:10:61:错误:非静态数据成员声明为'auto'            operator +(MyClass const&amp; a,MyClass const&amp; b)                                                                ^ prog.cpp:在函数'int main()'中:prog.cpp:25:15:错误:不匹配   'operator +'(操作数类型是'MyClass'和'MyClass')        auto z = x + y;                  ^