使用下面显示的定义,我可以使用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/