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
声明提供了命名空间级别函数的声明,但该声明仅在与之成为朋友的类内部可用。在本书提供的示例中,这不是问题:该函数接受两个封闭类型的参数,只要其中一个是封闭类型的,参数相关查找将在类的定义内部查找运算符。在您的情况下,情况并非如此,因为只有一个参数需要转换,所以编译器不会查看类的定义内部。
请注意,这与模板和转换无关:
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 An"; }
};
void f(int); // only declaration
int main() {
f(5); // "inside A"
}
不能对模板(以及所有实例化类型)执行此操作,因为友元声明是非模板化函数的声明。尽管您可以仅仅为了测试而使用代码:
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);
}
编译器不知道5是int
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 我的运算符重载友元函数无法理解模板类型 T 的问题
- 使用友元函数从多态类中检索类型信息
- 如何使用模板元编程在 C++17 中将一种类型转换为另一种类型
- 接受类参数的友元函数的尾随返回类型
- 具有自动和友元功能的返回类型匹配
- C++将友元添加到模板类中以便进行类型转换
- 指向友元函数中基类参数类型的指针
- C++中从用户定义类型到基元类型的隐式转换
- 模板化结构的友元函数,其参数类型取决于结构的内部
- 如何通过友元函数将一个对象(类型a)传递给另一个对象(类型b)的私有对象(类型a)
- 在基/派生类的成员函数/友元函数中派生* 到 Base* 的转换
- 模板友元函数和返回类型推导
- 用于类型转换的元函数
- 类内声明的友元运算符中左手参数的隐式转换
- 对于在类外定义的友元函数,模板上的隐式转换查找失败
- 类内友元函数的返回类型推导
- 通过友元函数重载运算符,并返回与rhs参数不同的类型
- 如何将l值元组类型转换为值元组类型