引入新模板参数的模板类的模板友元函数

Template friend function of template class that introduces a new template parameter

本文关键字:友元 函数 新模板 参数      更新时间:2023-10-16

感谢Daniel Frey对这篇文章的回答,我知道如何将模板友元函数声明给具有相同模板参数的模板类。不幸的是,使用其他模板参数声明友元函数的语法仍然逃脱了我。我想实现这样的事情:

template <typename T>
class Obj;
template <typename T>
Obj<T> make_obj(T t);
template <typename T, typename RetVal>
RetVal ret_obj(T t);
template <typename T>
class Obj {
private:
    T & t;
    Obj (T & t) : t(t) { }
    Obj() = delete;
    friend Obj make_obj<T>(T t);
    template <typename RetVal>
        friend RetVal ret_obj<T, RetVal>(T t);
};
template <typename T>
Obj<T> make_obj(T t) { 
    return Obj<T>(t);
}
template <typename T, typename RetVal>
RetVal ret_obj(T t) {
    return RetVal(make_obj(t).t);
}

我知道这篇文章中已经提出了同样的问题,但那里接受的答案似乎不是我想要的:将参数名称更改为 T2 使函数成为对象所有专业的朋友,而我想保持T与类相同。

不可能让friend声明引用部分专业化 - 它们要么引用特定的专业化,要么引用主模板。此外,函数模板无论如何都不能部分专用。
不过,函数模板无法实现的功能通常可以使用类模板:

template <typename T>
struct ret_obj_helper {
    // Here goes the original definition of ret_obj - the important difference
    // is the location of the template parameter T, which is the one
    // fixed by the friend declaration below
    template <typename RetVal>
    RetVal ret_obj(T t) {return RetVal(make_obj(t).t);}
};
// I guess RetVal, having to be explicitly specified, better goes first (?)
template <typename RetVal, typename T>
RetVal ret_obj(T&& t)
{
    // Overcomplicated for the sake of perfect forwarding
    return ret_obj_helper<typename std::remove_reference<T>::type>{}.
      template ret_obj<RetVal>(std::forward<T>(t));
}
template <typename T>
class Obj {
private:
    T t;
    Obj (T t) : t(t) { }
    Obj() = delete;
    friend Obj make_obj<T>(T t);
    // Make all specializations of the member function template 
    // of ret_obj_helper<T> a friend, regardless of the return type
    template <typename RetVal>
    friend RetVal ret_obj_helper<T>::ret_obj(T t);
};

演示