我正在尝试编写一个类,在最简单的示例中,其工作原理如下:
// Example program
#include <iostream>
#include <complex>
#include <typeinfo>
template<typename NumberType>
class SomeClass
{
public:
SomeClass(NumberType a_) : a(a_) {}
void get_number()
{
if (typeid(NumberType) == typeid(std::complex<double>))
std::cout << a.real() << " " << a.imag() << std::endl;
else
std::cout << a << std::endl;
}
private:
NumberType a;
};
int main()
{
int a=1;
std::complex<double> c(2.0,3);
SomeClass<int> A(a);
A.get_number();
SomeClass<std::complex<double>> C(c);
C.get_number();
return 0;
}
它基本上打印任何实数,但它应该将复数分成两个实数。
如果我按照显示的方式编译它,错误信息如下
In instantiation of 'void SomeClass<NumberType>::get_number() [with NumberType = int]':
28:18: required from here
14:46: error: request for member 'imag' in '((SomeClass<int>*)this)->SomeClass<int>::a', which is of non-class type 'int'
14:27: error: request for member 'real' in '((SomeClass<int>*)this)->SomeClass<int>::a', which is of non-class type 'int'
我理解,由于a
在第一种情况下的类型为int
,因此我无法在其上使用imag()
,因此会显示错误消息。
如何修改此类,以便在任意NumberType
模板参数的情况下执行我所需的操作?
答案 0 :(得分:2)
你应该使用模板和模板专门化,而不是typeid
- 在C ++中你想要使用编译时抽象,而不是根据变量或值的类型做出运行时决定。
您可以拥有以下独立的助手功能:
// General case:
template <typename T>
void get_number(const T& value)
{
std::cout << value << std::endl;
}
// Specialization for complex<double>
template <>
void get_number<std::complex<double> >(const std::complex<double>& value)
{
std::cout << value.real() << " " << value.imag() << std::endl;
}
// ... More specializations if you need to.
现在你可以致电:
get_number(3);
get_number(std::complex<double>(1, 2));
为了使其更通用,您可以使用std::complex<T>
代替std::complex<double>
。这需要更多的工作,因为不支持功能模板部分特化。您需要使get_number成为helper结构的静态成员,如下所示:
// General case:
template <typename T>
struct get_number_helper {
static void get(const T& value)
{
std::cout << value << std::endl;
}
};
// Specialization for complex<T>
template <typename T>
struct get_number_helper<std::complex<T> > {
static void get(const std::complex<T>& value)
{
std::cout << value.real() << " " << value.imag() << std::endl;
}
};
template<typename T>
void get_number(const T& value)
{
get_number_helper<T>::get(value);
}
答案 1 :(得分:2)
正如alexc已经提到的那样,当你使用std::complex<>::real
或{{1}时,你应该使用模板规范来阻止编译器看 imag
或int
成员作为数据类型。
会员模板规格更接近您现有的规格:
double