使用类型特征的部分 class 专业化
Partial class specialization using type traits
我是 C++ 的新手,我 运行 遇到了一个问题,我似乎无法解决或找不到其他有同样问题的人。
我有一个 class Polynomial
的定义:
template<class C>
class Polynomial {
std::vector<C> coefficients;
...
public:
...
const double integral(double, double);
...
};
我需要确保,如果 C
是整数类型,则无法调用 integral()
方法。显然这意味着使用类型特征,但是我已经尝试在方法本身上使用 template<typename = typename std::enable_if<!std::is_integral<C>::value, C>::type>
,虽然它可以编译,但我现在无法创建一个具有整数类型的对象作为模板参数。
然后我想,应该可以创建 Polynomial
class 的部分特化,即对 class 进行浮点特化,其中一个是整数和复数。类似于
template<typename C>
class Polynomial<typename std::enable_if<std::is_floating_point<C>::value, C>::type> : Polynomial<C> {
public:
const double integral(double, double);
};
然而,不管我怎么做,它似乎永远都行不通。
我想我的问题是:如何使用类型特征作为特化来指定 classes 的部分特化?
希望能帮到你
您需要一个单独的基础 class 用于通用内容,然后您可以像这样为 Polynomial
制作模板特化:
template<class C>
class PolynomialBase {
std::vector<C> coefficients;
};
template <typename T, typename Enable = void>
class Polynomial;
template<typename C>
class Polynomial<C, typename std::enable_if<!std::is_integral<C>::value>::type> : PolynomialBase<C> {
public:
const double integral(double, double);
};
template<typename C>
class Polynomial<C, typename std::enable_if<std::is_integral<C>::value>::type> : PolynomialBase<C> {};
来不及玩了?
显然,您可以通过专业化解决问题,krisz 的回答显示了一种可能的方法。
但是你可以通过SFINAE简单地enabling/disablingintegral()
解决
您无法检查 C
类型,因为 SFINAE 处理特定于该方法的模板,而不是 class 的模板,因此您必须使 integral()
成为模板方法。
举例
template <typename D = C>
std::enable_if_t<std::is_floating_point<D>::value, double>
integral (double, double)
{ return 1.0; }
通过这种方式,您可以检查 D
类型默认为 C
类型。
下面是一个完整的编译示例
#include <vector>
#include <type_traits>
template <typename C>
class Polynomial
{
private:
std::vector<C> coefficients;
public:
template <typename D = C>
std::enable_if_t<std::is_floating_point<D>::value, double>
integral (double, double)
{ return 1.0; }
};
int main()
{
Polynomial<float> pf;
Polynomial<int> pi;
pf.integral(0.0, 0.0); // compile
// pi.integral(0.0, 0.0); // compilation error
}
此解决方案的问题是,如果您显式 D
类型
,则可以 "hijacked"
Polynomial<int> pi;
// pi.integral(0.0, 0.0); // compilation error
pi.integral<double>(0.0, 0.0); // hijacked: compile
为避免劫持问题,您可以修改 integral()
的 SFINAE 测试,同时强加 C
和 D
是同一类型
所以如果你这样写
template <typename D = C>
std::enable_if_t<std::is_floating_point<D>::value
&& std::is_same<C, D>::value, double>
integral (double, double)
{ return 1.0; }
integral()
不能再被劫持了
Polynomial<int> pi;
// pi.integral(0.0, 0.0); // compilation error
// pi.integral<double>(0.0, 0.0); // compilation error
我是 C++ 的新手,我 运行 遇到了一个问题,我似乎无法解决或找不到其他有同样问题的人。
我有一个 class Polynomial
的定义:
template<class C>
class Polynomial {
std::vector<C> coefficients;
...
public:
...
const double integral(double, double);
...
};
我需要确保,如果 C
是整数类型,则无法调用 integral()
方法。显然这意味着使用类型特征,但是我已经尝试在方法本身上使用 template<typename = typename std::enable_if<!std::is_integral<C>::value, C>::type>
,虽然它可以编译,但我现在无法创建一个具有整数类型的对象作为模板参数。
然后我想,应该可以创建 Polynomial
class 的部分特化,即对 class 进行浮点特化,其中一个是整数和复数。类似于
template<typename C>
class Polynomial<typename std::enable_if<std::is_floating_point<C>::value, C>::type> : Polynomial<C> {
public:
const double integral(double, double);
};
然而,不管我怎么做,它似乎永远都行不通。
我想我的问题是:如何使用类型特征作为特化来指定 classes 的部分特化?
希望能帮到你
您需要一个单独的基础 class 用于通用内容,然后您可以像这样为 Polynomial
制作模板特化:
template<class C>
class PolynomialBase {
std::vector<C> coefficients;
};
template <typename T, typename Enable = void>
class Polynomial;
template<typename C>
class Polynomial<C, typename std::enable_if<!std::is_integral<C>::value>::type> : PolynomialBase<C> {
public:
const double integral(double, double);
};
template<typename C>
class Polynomial<C, typename std::enable_if<std::is_integral<C>::value>::type> : PolynomialBase<C> {};
来不及玩了?
显然,您可以通过专业化解决问题,krisz 的回答显示了一种可能的方法。
但是你可以通过SFINAE简单地enabling/disablingintegral()
解决
您无法检查 C
类型,因为 SFINAE 处理特定于该方法的模板,而不是 class 的模板,因此您必须使 integral()
成为模板方法。
举例
template <typename D = C>
std::enable_if_t<std::is_floating_point<D>::value, double>
integral (double, double)
{ return 1.0; }
通过这种方式,您可以检查 D
类型默认为 C
类型。
下面是一个完整的编译示例
#include <vector>
#include <type_traits>
template <typename C>
class Polynomial
{
private:
std::vector<C> coefficients;
public:
template <typename D = C>
std::enable_if_t<std::is_floating_point<D>::value, double>
integral (double, double)
{ return 1.0; }
};
int main()
{
Polynomial<float> pf;
Polynomial<int> pi;
pf.integral(0.0, 0.0); // compile
// pi.integral(0.0, 0.0); // compilation error
}
此解决方案的问题是,如果您显式 D
类型
Polynomial<int> pi;
// pi.integral(0.0, 0.0); // compilation error
pi.integral<double>(0.0, 0.0); // hijacked: compile
为避免劫持问题,您可以修改 integral()
的 SFINAE 测试,同时强加 C
和 D
是同一类型
所以如果你这样写
template <typename D = C>
std::enable_if_t<std::is_floating_point<D>::value
&& std::is_same<C, D>::value, double>
integral (double, double)
{ return 1.0; }
integral()
不能再被劫持了
Polynomial<int> pi;
// pi.integral(0.0, 0.0); // compilation error
// pi.integral<double>(0.0, 0.0); // compilation error