Templated class: 在编译时检查是否复杂
Templated class: Check if complex at compile time
我有一个 class A
模板,其中 Scalar
可以是实值或复值。它有一个方法 realPart
应该 return 数字的实部。如果 Scalar
是实数值,它应该只是 return 原始标量,如果它是复数类型,它应该是 .real()
。
写作时
#include <complex>
#include <iostream>
template<class Scalar>
class A {
public:
A (const Scalar z):
z_(z)
{
}
Scalar realPart()
{
return z_.real();
}
private:
Scalar z_;
};
int main() {
A<std::complex<double>> z0((1.0, 2.0));
std::cout << z0.realPart() << std::endl; // check
A<double> z1(1.0);
std::cout << z1.realPart() << std::endl; // mööp
}
编译器会在 z1.realPart()
报错,因为 double
不知道 .real()
。
如何在编译时保护.real()
?
这可以通过简单的 is_complex
特征和 SFINAE 来完成:
template<class T> struct is_complex : std::false_type {};
template<class T> struct is_complex<std::complex<T>> : std::true_type {};
template<class Scalar>
class A {
public:
A(const Scalar z) : z_(z)
{ }
template<class S = Scalar, std::enable_if_t<is_complex<S>{}>* = nullptr>
Scalar realPart()
{
return z_.real();
}
template<class S = Scalar, std::enable_if_t<!is_complex<S>{}>* = nullptr>
Scalar realPart()
{
return z_;
}
private:
Scalar z_;
};
我有一个 class A
模板,其中 Scalar
可以是实值或复值。它有一个方法 realPart
应该 return 数字的实部。如果 Scalar
是实数值,它应该只是 return 原始标量,如果它是复数类型,它应该是 .real()
。
写作时
#include <complex>
#include <iostream>
template<class Scalar>
class A {
public:
A (const Scalar z):
z_(z)
{
}
Scalar realPart()
{
return z_.real();
}
private:
Scalar z_;
};
int main() {
A<std::complex<double>> z0((1.0, 2.0));
std::cout << z0.realPart() << std::endl; // check
A<double> z1(1.0);
std::cout << z1.realPart() << std::endl; // mööp
}
编译器会在 z1.realPart()
报错,因为 double
不知道 .real()
。
如何在编译时保护.real()
?
这可以通过简单的 is_complex
特征和 SFINAE 来完成:
template<class T> struct is_complex : std::false_type {};
template<class T> struct is_complex<std::complex<T>> : std::true_type {};
template<class Scalar>
class A {
public:
A(const Scalar z) : z_(z)
{ }
template<class S = Scalar, std::enable_if_t<is_complex<S>{}>* = nullptr>
Scalar realPart()
{
return z_.real();
}
template<class S = Scalar, std::enable_if_t<!is_complex<S>{}>* = nullptr>
Scalar realPart()
{
return z_;
}
private:
Scalar z_;
};