如何根据类模板参数禁用成员函数?



为了说明这种情况,让我们假设一个最小的例子:一个Vector模板类将其维度作为非类型模板参数。当维度允许时,此类将提供x()y()(等(访问器:

template <int N_dimension>
class Vector
{
public:
// ctors, etc.    
int &x();
template <class = std::enable_if_t<(N_dimension>2)>> int &y();
private:
std::array<int, N_dimension> mData;
};

然而,这不起作用,因为enable_if只能应用于推导的模板参数。

我们当前的解决方法看起来很麻烦:

template <int N=N_dimension, class = std::enable_if_t<(N>2)>> int &y();

此外,它还需要在定义中使用静态断言来确保它是万无一失的(因为现在客户端代码可以为与实际维度不匹配的N提供显式值。编辑:或匿名第二个模板参数的显式值,如谢尔盖指出的那样(。


有没有更直接的方法在C++中表达这一点?

我会在这里取消 SFINAE,简单地将代码拆分为接口和私有实现,如下所示:

int& y() {
return y_impl(std::bool_constant<N > 2>{});
}
private:
int& y_impl(std::true_type ) {
// impl
}
int& y_impl(std::false_type ) {
static_assert(N > 2 /* always false */, "Wrong number of dimensions!");
}

这里的拆分是假设yN <= 2时不可编译,以减少错误消息的混乱。如果不是这种情况,y体内的一次static_assert就足够了。

在 C++20 中,您可以简单地使用requires丢弃方法:

template <int N>
class Vector
{
public:
int &x();
int &y() requires(N >= 2);
private:
std::array<int, N_dimension> mData;
};

在以前的版本中,它更详细:

template <std::size_t N>
class Vector
{
public:
int &x();
template <std::size_t M = N, std::enable_if_t<(M >= 2 && M == N), int> = 0>
int &y();
private:
std::array<int, N_dimension> mData;
};

相关内容

  • 没有找到相关文章

最新更新