引入新模板参数的模板 class 的模板友元函数
Template friend function of template class that introduces a new template parameter
感谢 Daniel Frey 对 this post 的回答,我知道如何使用相同的模板参数向模板 class 声明模板友元函数。不幸的是,我仍然无法理解使用附加模板参数声明友元函数的语法。我想实现这样的目标:
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);
}
我知道在 this post 中已经问过同样的问题,但那里接受的答案似乎不是我想要的:将参数名称更改为 T2
使函数成为对象所有特化的朋友,而我想保持 T
与 class 中的相同。
不可能让 friend
声明引用部分特化 - 它们要么引用特定的特化,要么引用主模板。此外,函数模板无论如何都不能部分特化。
使用 class 模板通常可以实现函数模板无法实现的功能:
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);
};
Demo.
感谢 Daniel Frey 对 this post 的回答,我知道如何使用相同的模板参数向模板 class 声明模板友元函数。不幸的是,我仍然无法理解使用附加模板参数声明友元函数的语法。我想实现这样的目标:
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);
}
我知道在 this post 中已经问过同样的问题,但那里接受的答案似乎不是我想要的:将参数名称更改为 T2
使函数成为对象所有特化的朋友,而我想保持 T
与 class 中的相同。
不可能让 friend
声明引用部分特化 - 它们要么引用特定的特化,要么引用主模板。此外,函数模板无论如何都不能部分特化。
使用 class 模板通常可以实现函数模板无法实现的功能:
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);
};
Demo.