繁体   English   中英

C ++将朋友添加到模板类以进行类型转换

[英]C++ adding friend to a template class in order to typecast

我目前正在阅读“有效的C ++”,其中有一章包含与此类似的代码:

template <typename T>
class Num {
public:
  Num(int n) { ... }
};

template <typename T>
Num<T> operator*(const Num<T>& lhs, const Num<T>& rhs) { ... }

Num<int> n = 5 * Num<int>(10);

这本书说,这是行不通的(实际上是行不通的),因为您不能期望编译器使用隐式类型转换来专门化模板。

作为解决方案,建议使用“ friend”语法在类内部定义函数。

//It works
template <typename T>
class Num {
public:
  Num(int n) { ... }

  friend 
  Num operator*(const Num& lhs, const Num& rhs) { ... }
};

Num<int> n = 5 * Num<int>(10);

并且该书建议每当我需要隐式转换为模板类类型时都使用此朋友声明。 一切似乎都有意义。

但是,为什么不能得到使用公共函数而不是运算符的相同示例?

template <typename T>
class Num {
public:
  Num(int n) { ... }

  friend 
  void doFoo(const Num& lhs) { ... }
};

doFoo(5);

这次,编译器抱怨他根本找不到任何“ doFoo”。 而且,如果我在类外声明doFoo,则会收到合理的不匹配类型错误。 好像“朋友...”部分只是被忽略。

我的理解有问题吗? 在这种情况下,函数和运算符有什么区别?

原因是在这里

doFoo(5);

给定一个int参数,编译器无法找到foo 这相当于像这样调用您的朋友运算符:

Num<int> n = 5 * 10;

这将“起作用”,但不是通过调用您的Num类中定义的friend operator* ,而是通过调用内置operator*的整数,然后使用Num的转换构造函数的隐式转换来实现。

核心问题是查找。 friend声明提供了名称空间级别功能的声明,但是该声明仅在与其成为friend的类中可用。 在书中提供的示例中,这不是问题:该函数采用封闭类型的两个参数,只要其中一个为封闭类型,则“依赖于参数的查询”将在类的定义内查找并找到运算符。 在您的情况下不是这样,因为只有一个参数并且需要转换,所以编译器将不会在类的定义内查找。

请注意,这与模板和转换无关:

class A {
   friend void f( int ) {}
   friend void g( int, A ) {}
};
int main() {
   f(5);           // Error: lookup cannot find 'f' declared *only* inside A
   g(5,A());       // Ok, one argument is 'A', lookup will find the function
}

在上述情况下,不涉及任何模板,您可能会在名称空间级别添加一个声明来修复它,但这并不是模板类的真正选择。

class A {
   friend void f() { std::cout << "inside A\n"; }
};
void f(int);     // only declaration
int main() {
   f(5);         // "inside A"
}

对于模板(以及所有实例化类型),无法完成此操作,因为friend声明是非模板函数的声明。 尽管您可以仅出于测试目的就可以使用代码:

template <typename T>
struct Num {
   Num(int x) ...
   friend void f( Num const & );
};
Num<int> f(Num<int> const &);    // only declaration
int main() {
   f(5);
}

是的,这些代码编译器不知道如何使用它。 就像doFoo(5)

编译器不知道5是int

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM