模板成员超载的Sfinae

SFINAE on template member overloading

本文关键字:Sfinae 超载 成员      更新时间:2023-10-16

我想专门提高 getVector成员函数,我正在尝试为此使用sfinae。但是它仅在昏暗的3或更高时起作用。

template <size_t Dim>
class Mat
{
    ...
    template <size_t VDim, typename enable_if<(Dim > 1 && VDim == 0)>::type* = nullptr>
        void getVectorBegin(const array<size_t, Dim - 1>& indexAfter) const;
    template <size_t VDim, typename enable_if<(Dim > 2 && 0 < VDim && VDim < Dim-1)>::type* = nullptr>
        void getVectorBegin(const array<size_t, VDim>& indexBefore, const array<size_t, Dim - VDim - 1>& indexAfter) const;
    template <size_t VDim, typename enable_if<(Dim > 1 && VDim == Dim-1)>::type* = nullptr>
        void getVectorBegin(const array<size_t, Dim - 1>& indexBefore) const;
};
Mat<3> m;
Mat<2> m; // error C2039: 'type': is not a member of 'std::enable_if<false,_Ty>'

这将很棘手。

我相信您的代码对Dim>=2是可以的,但是当给出Dim<=1参数时,它的形式不佳,而无需诊断,但出于不同的原因,您的编译器会抱怨。


对于Dim>=2,这是正确的,但是您的编译器(MSVC )在Dim==2情况下抱怨。考虑到错误描述,我认为原因是它错误地短路了&amp;&amp;在enable_if条件下的表达式,将它们解释为cC_7是false时类模板参数上的值依赖性。解决方法是将Dim > x检查作为&amp;&amp;的最后一个学期的检查。表达。

为了详细说明,情况在概念上与以下代码段相似:

template <size_t N>
class foo
{
    template <typename E = enable_if_t<(N>0)>>
    void bar();
};
foo<1> f1;
foo<0> f0; // fails

在这里,foo的实例触发了其成员声明(但没有定义)的实例(请参见 [temp.inst]#1 );但是,仅检查依赖成员模板参数的名称和表达式被推迟在其各自的实例化点上。在这里,类型名称 enable_if_t<(N>0)> di di dim 取决于任何bar()模板参数(N属于foo的模板参数列表)是非依赖性的,因此在enable_if<false>::type中导致CC_14当N == 0时,因此出现错误。bk_hr>

回到您的代码,请考虑:

[temp.dep.constexpr]#1 除非如下所述,恒定表达式是值依赖的如果任何子表达是值依赖的

和任何地方都没有提到一个例外。因此,即使 Dim<=1Dim > 1 && VDim == 0的表达也是值依赖的。因此,在替换VDim之前,不应发生任何错误(SFINAE将适用)。实际上,GCC和Clang都同意接受您的代码。

也就是说,当Dim<=1第一个和第三个getVectorBegin Overloads实际上声明功能等效成员模板(请参阅 [temp.over.link]#6 ),所以我相信在那种情况下,它是不明式的。