C++ Template类的Template friend函数,该函数引入了新的模板参数
感谢Daniel Frey对的回答,我知道如何使用相同的模板参数向模板类声明模板友元函数。不幸的是,我仍然无法理解用附加模板参数声明友元函数的语法。我想实现这样的目标:C++ Template类的Template friend函数,该函数引入了新的模板参数,c++,templates,friend,C++,Templates,Friend,感谢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); t
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);
}
模板
Obj类;
模板
Obj make_Obj(T);
模板
检索检索对象(T T);
模板
Obj类{
私人:
T&T;
Obj(T&T):T(T){}
Obj()=删除;
朋友对象使_Obj(T);
模板
朋友关系(T T);
};
模板
Obj make_Obj(T){
返回Obj(t);
}
模板
检索检索对象(T){
返回返回值(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);
};
模板
结构检索对象辅助对象{
//这里是ret_obj的原始定义——重要的区别
//是模板参数T的位置,它是
//由下面的好友声明修复
模板
RetVal ret_obj(T){return RetVal(make_obj(T).T);}
};
//我想,必须明确指定RetVal,最好先执行(?)
模板
检索检索对象(T&T)
{
//为了实现完美的转发而过度复杂
返回ret_obj_helper{}。
模板ret_obj(标准:正向(t));
}
模板
Obj类{
私人:
T;
Obj(T):T(T){}
Obj()=删除;
朋友对象使_Obj(T);
//对成员函数模板进行所有专门化
//无论返回类型如何,都可以将ret_obj_helper作为朋友
模板
朋友RetVal ret_obj_helper::ret_obj(T);
};
.作为猜测,我会说“你不能”。有一些变通方法可以让它工作,比如说通过helper
struct
反弹函数。这是不可能的。朋友声明不能声明部分专门化。@Yakk是的,我想我可以使用另一个类,如果必须的话,我会使用它;我只是想知道是否有一种直接的方法可以做到这一点。如果不是,那就太糟糕了(@T.C.而且函数也没有部分专门化。嗯:你能把一个使用别名作为朋友吗?是的,读了上面的评论后我就知道它会归结为这个。不过我有一个问题:如果不删除引用,用一个来调用函数将不会编译?使用公共结构而不是一个公共静态成员?我看不出封装的程度有什么不同。因为公共函数不能是朋友,它必须通过一个丑陋的公共接口。