Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Template类的Template friend函数,该函数引入了新的模板参数_C++_Templates_Friend - Fatal编程技术网

C++ Template类的Template friend函数,该函数引入了新的模板参数

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

感谢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);
}
模板
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.而且函数也没有部分专门化。嗯:你能把一个使用别名作为朋友吗?是的,读了上面的评论后我就知道它会归结为这个。不过我有一个问题:如果不删除引用,用一个来调用函数将不会编译?使用公共结构而不是一个公共静态成员?我看不出封装的程度有什么不同。因为公共函数不能是朋友,它必须通过一个丑陋的公共接口。