【问题标题】:Friend declaration outside the class definition for template and implcit constructor模板和隐式构造函数的类定义之外的友元声明
【发布时间】:2017-08-04 22:03:15
【问题描述】:

我希望我的重载 operator+ 可以用于混合类型。 非模板类没有问题。 为了使它与 template 类一起工作,我在类中添加了一个 friend operator+ 并且它可以工作。

template <typename T> class Wrapper
{
    T _val;
public:
    Wrapper(T val) :_val(val){}
    T getValue() const { return _val; }

    friend Wrapper<T> operator+(const Wrapper<T>& val1, const Wrapper<T>& val2)
    {
        return Wrapper<T>(val1.getValue() + val2.getValue());
    }
};

int main()
{
    Wrapper<int> v1 = 10; // OK, implicit constructor
    Wrapper<int> v2(20);
    Wrapper<int> result1 = v1 + v2; // OK, both values are of type Wrapper<int>
    Wrapper<int> result2 = v1 + 40; // Ok, casting by implicit constructor works
    return 0;
}

现在我想像这样将 operator+ 实现移到类之外:

#include <iostream>
#include <string>

template <typename T> class Wrapper;

template <typename T> Wrapper<T> operator+(const Wrapper<T>& val1, const Wrapper<T>& val2);

template <typename T> class Wrapper
{
    T _val;
public:
    Wrapper(T val) :_val(val){}
    T getValue() const { return _val; }

    friend Wrapper<T> operator+ <>(const Wrapper<T>& val1, const Wrapper<T>& val2);
};

// template<class T> Wrapper<T> operator+(const Wrapper<T>&, const Wrapper<T>&)
// template argument deduction/substitution failed
template <typename T> Wrapper<T> operator+(const Wrapper<T>& val1, const Wrapper<T>& val2)
{
    return Wrapper<T>(val1.getValue() + val2.getValue());
}

int main()
{
    Wrapper<int> v1 = 10; // OK, implicit constructor
    Wrapper<int> v2(20);
    Wrapper<int> result1 = v1 + v2; // OK, both values are of type Wrapper<int>

    // note: mismatched types 'const Wrapper<T>' and 'int'
    Wrapper<int> result2 = v1 + 40; // Error
    return 0;

}

但它给了我编译错误(将它们粘贴到上面的代码中)。 有办法解决吗?

http://cpp.sh/5j5zg(工作中) http://cpp.sh/9saow(不工作)

【问题讨论】:

标签: c++ templates metaprogramming


【解决方案1】:

创建这样一个不是模板函数的友元函数有点奇怪。但是,您可以稍微更改一下以使其正常工作,方法是将 friend operator+ 设为模板函数:

template <typename T>
class Wrapper
{
    T _val;
public:
    Wrapper(T val) :_val(val){}
    T getValue() const { return _val; }

    template <typename U>
    friend Wrapper<U> operator+(const Wrapper<U>& val1, const Wrapper<U>& val2);
};

template <typename T>
Wrapper<T> operator+(const Wrapper<T>& val1, const Wrapper<T>& val2)
{
    return Wrapper<T>(val1.getValue() + val2.getValue());
}

这几乎可以按您的意愿工作,但是由于这是一个模板函数,因此禁用了隐式转换。不过,重新添加它们很容易:

template <typename T>
Wrapper<T> operator+(const Wrapper<T>& val1, const T& val2)
{
    return Wrapper<T>{ val1.getValue() + val2 };
}

template <typename T>
Wrapper<T> operator+(const T& val1, const Wrapper<T>& val2)
{
    return Wrapper<T>{ val1 + val2.getValue() };
}

Live on Coliru

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 2018-02-22
    • 2018-06-11
    • 2022-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多