![](/img/trans.png)
[英]How to define a template class template friend function which one of its parameters is a dependent name outside the template class body?
[英]How to define a friend template function of a template class outside of its declaration?
如果我在模板类声明中定义朋友模板函数,如下所示,则可以编译它。
#include <iostream>
template <typename T>
class X {
public:
X(int i) : n(i) {}
private:
T n;
template <typename U>
friend void doStuff(const X<T>& x, const U& u)
{
std::cout << (x.n + u) << std::endl;
}
};
int main()
{
X<int> x(1);
doStuff(x, 3);
return 0;
}
但是,如果将doStuff()
的定义从类声明中移出,则在声明类X<>
,如下所示,它将无法编译。
template <typename U>
template <typename T>
void doStuff(const X<T>& x, const U& u)
{
std::cout << (x.n + u) << std::endl;
}
以下代码也没有。
template <typename U, typename T>
void doStuff(const X<T>& x, const U& u)
{
std::cout << (x.n + u) << std::endl;
}
那么,如何在类声明之外定义模板函数doStuff()
?
提前致谢。
也许像这样:
template <typename T>
class X {
public:
X(int i) : n(i) {}
private:
T n;
template <typename U, typename V>
friend void doStuff(const X<U>& x, const V& u);
};
template <typename U, typename V>
void doStuff(const X<U>& x, const V& u)
{
std::cout << (x.n + u) << std::endl;
}
int main()
{
X<int> x(1);
doStuff(x, 3);
X<double> y(1.0);
doStuff(y, 3.5);
}
@jrok提供了一个很好的解决方案。
通过将函数声明为
template <typename U, typename V>
friend void doStuff(const X<U>& x, const V& u);
您说每个X和V都有一个函数doStuff。但是然后您问,如果U不是T呢? 好吧,当您使用X类型为int的参数调用doStuff时,模板参数推导的唯一可接受结果是将类定义的类型T设置为int。
template <typename V>
friend void doStuff(const X<T>& x, const V& u);
?
实际上,确实可以。 但这意味着对于任何类型T
, 您都告诉编译器要为任何必需的T
定义一个采用X<T>
的函数,并且第二个参数是模板参数。 请注意,第一个参数不是模板函数参数。
没有通用的说法:“每当用户使用X<T>
类型的类时,请使用此特定模式来定义函数doStuff,其中X<T>
是第一个参数。
因此,在该类中,您曾承诺它会存在,但无法以模板方式编写定义。 它必须像
template <typename T,typename U>
for_any_seen_template_instance_anywhere_in_the_program_< X<T> >::
void doStuff(const X<U>& x, const V& u){
... code.
}
没有这样的事情。 思考的另一种方式:当您写作时
doStuff(a,b);
如果第一个参数不是函数模板参数,则不会自动生成该第一个参数的任何内容。 类模板的模板参数类型不会像模板功能参数一样自动推导。
但是,您可以为任何必需的T
定义X<T>
(如声明中所承诺的),但是您必须为每种必需的类型自己做:
template<typename V>
void doStuff(const X<int>& x, const V& u){
std::cout << (x.n + u) << std::endl;
}
编辑 ,回答下面的评论。
的确,例如,所有doStuff(X<U>,int)
都是任何X<T>
朋友,而与T
和U
类型无关。 这意味着在doStuff主体内部,您可以访问X<Q>
类型的对象的私有对象。 在这种情况下,您没有将任何此类对象传递给函数,但可以在其中创建X<std::string>
并使用它的私有函数。 这是您为不使用原始内联而支付的价格。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.