使用下面显示的定义,我可以使用G++(4.7.2)调用qget<0>()qget<1>(),但是qget<2>或“高级”将失败,并出现no matching function错误。同时,Clang++(3.2)失败了。我已经将懒惰的enable_if作为最后的手段。尽管我认为我不需要它。我知道代码看起来有些奇怪,但是谁能看到错误的根源? (Boost提供了enable_if类。)

template <typename T> struct Tid { typedef T type; };

template <unsigned I>
typename enable_if_c<(I==0),double>::type
qget()
{ return 0.0; }

template <unsigned I>
typename lazy_enable_if_c<(I!=0), Tid<decltype(qget<I-1>())>>::type
qget()
{ return qget<I-1>(); }

最佳答案

当您将功能或功能模板声明为例如ret foo(A, B, C);或与auto foo(A, B, C) -> ret;无关,那么引用刚刚声明的实体的foo不在所谓的声明器之后。在您的特定情况下,返回类型(无论是否为延迟返回类型)始终是声明符的一部分。

这意味着在您的最后一个声明中,返回类型中的名称qget可能引用先前的声明(I==0的情况),但可能永远不会引用当前的声明。这就是为什么找到qget<0>qget<1>却未找到qget<2>的原因:尝试形成后者的返回类型时,未找到qget<1>,因为第一个声明按预期被SFINAE输出,第二个声明是当前声明,并且不在范围内。该错误导致SFINAE。

发生这种情况时(通常不多说),我通常的解决方案是使用struct(作为实现细节),因为所有成员函数(和成员函数模板)都从类的定义中开始声明。撑紧。

话虽如此,您仍然会遇到障碍,因为即使您使用lazy_enable_if_c,即使qget<I - 1>()lazy_enable_if_c,您仍然仍在急切地计算I的类型(作为0的参数)。懒惰地评估所述类型的身份并不能挽救您。

不幸的是,我似乎无法得到使用GCC 4.7.2运行的示例,该示例坚持即使在将条件固定为I > 0并使用惰性结果的情况下也不会终止递归(尽管通常我会使用4.8),所以我可以保证您可以使用我的解决方案。

关于c++ - 懒惰enable_if在工作上 sleep 吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12699790/

10-11 18:48