提问人:Darnoc Eloc 提问时间:6/11/2022 更新时间:6/19/2022 访问量:147
模棱两可的类模板转换
Ambiguous Class Template Conversion
问:
如何将模板构造函数添加到类中,以便显式地执行从复杂到复杂的复制初始化,而不会产生歧义?是否有与编译器和 C++ 版本/标准无关的解决方案?有没有一种方法只需要定义构造函数而不需要额外的运算符重载?
我包含模板复制构造函数和运算符重载(类中定义的最后两个方法),但编译器给了我以下消息。
Compilation error
main.cpp: In function ‘void testTemplateConstructor()’:
main.cpp:74:27: error: conversion from ‘complex<float>’ to ‘complex<double>’ is ambiguous
complex<double> cd = cf;
^~
main.cpp:35:5: note: candidate: complex<T>::operator complex<X>() [with X = double; T = float]
operator complex<X>(){
^~~~~~~~
main.cpp:29:5: note: candidate: complex<T>::complex(complex<X>&) [with X = float; T = double]
complex(complex<X>& arg) {
^~~~~~~
这是正在使用的测试用例。
void testTemplateConstructor() {
complex<float> cf{1.0f, 2.0f};
complex<double> cd = cf;
Assert(cf.real()==cd.real(), "Real parts are different.");
Assert(cf.imag()==cd.imag(), "Imaginary parts are different.");
}
template <typename T> class complex{
private:
typedef complex<T> complexi;
T real_;
T imag_;
public:
complex(){
real_ = 0;
imag_ = 0;
}
complex(T a, T b){
real_ = a;
imag_ = b;
}
complex(T a){
real_ = a;
}
complex(complex<T>& comp){
real_ = comp.real_;
imag_ = comp.imag_;
}
template <typename X>
complex(complex<X>& arg) {
real_ = arg.real_;
imag_ = arg.imag_;
}
template <typename X>
operator complex<X>(){
return complex<T>();
}
};
答:
1赞
user12002570
6/11/2022
#1
这样,从复杂到复杂之间的复制初始化是显式执行的,没有歧义?是否有与编译器和 C++ 版本/标准无关的解决方案?
是的,在这个特定示例中,您可以向 ctor 的参数添加一个低级别。const
template <typename T> class complex{
public:
typedef complex<T> complexi;
T real_;
T imag_;
public:
complex(){
real_ = 0;
imag_ = 0;
}
complex(T a, T b){
real_ = a;
imag_ = b;
}
complex(T a){
real_ = a;
}
complex(const complex<T>& comp){
std::cout<<"nornal version";;
real_ = comp.real_;
imag_ = comp.imag_;
}
template <typename X>
complex(const complex<X>& arg) {
std::cout<<"template version";;
real_ = arg.real_;
imag_ = arg.imag_;
}
};
void testTemplateConstructor() {
complex<float> cf{1.0f, 2.0f};
complex<double> cd = cf;
}
评论
0赞
Goswin von Brederlow
6/11/2022
你甚至需要它们吗?他们不是在做同样的事情吗?
0赞
user12002570
6/11/2022
@GoswinvonBrederlow OP 在问题中没有提到完全删除其中一个也是一种选择。否则,这样做是消除歧义的明显方法。无论如何,我已经在答案的末尾添加了这一点,尽管我认为 OP 已经意识到了这一点。
0赞
Goswin von Brederlow
6/11/2022
我只是想知道是否有任何情况,您需要其中一个而另一个不起作用,反之亦然。有没有两者都需要的情况?
1赞
user12002570
6/12/2022
如果您在模板化构造函数中添加低级常量,它适用于所有编译器和所有 C++ 版本。请参阅使用 const 的工作演示。请注意,在上面的演示链接中,我添加了一个并用注释突出显示了它,以便于发现。我在回答中添加了相同的内容。看看我更新的答案。const
0赞
Darnoc Eloc
6/19/2022
#2
这就是我一直在寻找的解决方案,它适用于 C++11 标准和编译器版本,x86_64 gcc 4.7.1 和 clang 3.4.1。除了使用static_cast之外,唯一的区别是 getter 的使用。
using namespace std;
template <typename T> class complex{
public:
typedef complex<T> complexi;
T real_;
T imag_;
public:
complex(){
real_ = 0;
imag_ = 0;
}
complex(T a, T b){
real_ = a;
imag_ = b;
}
complex(T a){
real_ = a;
}
complex(const complex<T>& comp){
real_ = comp.real_;
imag_ = comp.imag_;
}
template <typename X>
complex(const complex<X>& rhs){
real_ = static_cast<T>(rhs.real());
imag_ = static_cast<T>(rhs.imag());
}
T real() const {
return real_;
}
T imag() const {
return imag_;
}
};
评论