模板专业化:“标量”不命名类型
Template specialization: ‘Scalar’ does not name a type
我正在尝试为 complex
标量实现模板专业化,并且使用 开始使用 std::enable_if_t
及其穷人版本
#include <type_traits>
#include <complex>
// declarations
namespace Test {
template<class Scalar>
class A {
public:
A(const Scalar z);
Scalar realPart();
private:
Scalar z_;
};
}
// definitions
namespace Test {
template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;
template<class T> struct is_complex : std::false_type {};
template<class T> struct is_complex<std::complex<T>> : std::true_type {};
template<class Scalar>
A<Scalar>::
A(const Scalar z) : z_(z)
{ }
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
Scalar
A<Scalar>::realPart()
{
return z_.real();
}
template<class S = Scalar, enable_if_t<!is_complex<S>{}>* = nullptr>
Scalar
A<Scalar>::realPart()
{
return z_;
}
}
int main() {
}
对于 C++11。然而,上面的代码,将声明和定义分开,无法编译
test4.cpp:29:22: error: ‘Scalar’ does not name a type
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
^
我不清楚这是怎么失败的。有什么提示吗?
我手边没有编译器,但我认为:
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
A<Scalar>::
Scalar realPart()
{
return z_.real();
}
应该是:
template<typename Scalar, enable_if_t<is_complex<Scalar>{}>* = nullptr>
// ^^^^^^^^^^^^^^^ ^^^^^^
typename Scalar A<Scalar>::realPart()
//^^^^^^^^^^^^^^^^^^^^^^^^^
{
return z_.real();
}
...其他定义也一样。
在此代码中:
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
Scalar A<Scalar>::realPart()
{
return z_.real();
}
Scalar
没有命名类型,因为它不是一个。那只是您一直在使用的模板参数的名称。您原本打算写的是:
template<class Scalar, enable_if_t<is_complex<Scalar>{}>* = nullptr>
Scalar A<Scalar>::realPart()
{
return z_.real();
}
但是,这也不起作用,因为 A
没有第二个模板非类型参数,而您正试图将其传递给它。你真正想做的是部分特化成员函数A<Scalar>::realPart()
,这在语言中是不可能的。
您需要做的是派遣一个知道该做什么的助手。类似于:
template <class Scalar>
Scalar A<Scalar>::realPart() {
return getRealPart(z_);
}
与:
template <typename Scalar>
Scalar getRealPart(Scalar r) { return r; }
template <typename Scalar>
Scalar getRealPart(std::complex<Scalar> c) { return c.real(); }
对于更复杂的类型特征,我们会做类似的事情:
template <class Scalar>
Scalar A<Scalar>::realPart() {
return getRealPart(z_, is_complex<Scalar>{});
}
并且有重载以 true_type
和 false_type
作为第二个参数。在这种特殊情况下,这是不必要的。
我正在尝试为 complex
标量实现模板专业化,并且使用 std::enable_if_t
及其穷人版本
#include <type_traits>
#include <complex>
// declarations
namespace Test {
template<class Scalar>
class A {
public:
A(const Scalar z);
Scalar realPart();
private:
Scalar z_;
};
}
// definitions
namespace Test {
template<bool B, class T = void>
using enable_if_t = typename std::enable_if<B,T>::type;
template<class T> struct is_complex : std::false_type {};
template<class T> struct is_complex<std::complex<T>> : std::true_type {};
template<class Scalar>
A<Scalar>::
A(const Scalar z) : z_(z)
{ }
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
Scalar
A<Scalar>::realPart()
{
return z_.real();
}
template<class S = Scalar, enable_if_t<!is_complex<S>{}>* = nullptr>
Scalar
A<Scalar>::realPart()
{
return z_;
}
}
int main() {
}
对于 C++11。然而,上面的代码,将声明和定义分开,无法编译
test4.cpp:29:22: error: ‘Scalar’ does not name a type
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
^
我不清楚这是怎么失败的。有什么提示吗?
我手边没有编译器,但我认为:
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
A<Scalar>::
Scalar realPart()
{
return z_.real();
}
应该是:
template<typename Scalar, enable_if_t<is_complex<Scalar>{}>* = nullptr>
// ^^^^^^^^^^^^^^^ ^^^^^^
typename Scalar A<Scalar>::realPart()
//^^^^^^^^^^^^^^^^^^^^^^^^^
{
return z_.real();
}
...其他定义也一样。
在此代码中:
template<class S = Scalar, enable_if_t<is_complex<S>{}>* = nullptr>
Scalar A<Scalar>::realPart()
{
return z_.real();
}
Scalar
没有命名类型,因为它不是一个。那只是您一直在使用的模板参数的名称。您原本打算写的是:
template<class Scalar, enable_if_t<is_complex<Scalar>{}>* = nullptr>
Scalar A<Scalar>::realPart()
{
return z_.real();
}
但是,这也不起作用,因为 A
没有第二个模板非类型参数,而您正试图将其传递给它。你真正想做的是部分特化成员函数A<Scalar>::realPart()
,这在语言中是不可能的。
您需要做的是派遣一个知道该做什么的助手。类似于:
template <class Scalar>
Scalar A<Scalar>::realPart() {
return getRealPart(z_);
}
与:
template <typename Scalar>
Scalar getRealPart(Scalar r) { return r; }
template <typename Scalar>
Scalar getRealPart(std::complex<Scalar> c) { return c.real(); }
对于更复杂的类型特征,我们会做类似的事情:
template <class Scalar>
Scalar A<Scalar>::realPart() {
return getRealPart(z_, is_complex<Scalar>{});
}
并且有重载以 true_type
和 false_type
作为第二个参数。在这种特殊情况下,这是不必要的。