【问题标题】:Lazy enable_if sleeping on the job?懒惰的 enable_if 在工作中睡觉?
【发布时间】:2012-10-02 23:14:46
【问题描述】:

使用下面显示的定义,我可以使用 G++ (4.7.2) 调用 qget<0>()qget<1>(),但 qget<2> 或“更高”将失败并出现 no matching function 错误。同时,Clang++ (3.2) 中的任何一个都失败了。我使用 lazy 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>(); }

【问题讨论】:

    标签: c++ templates c++11 sfinae enable-if


    【解决方案1】:

    当您将函数或函数模板声明为例如ret foo(A, B, C); 或无所谓 auto foo(A, B, C) -&gt; ret;,那么引用刚刚声明的实体的 foo 直到所谓的声明符之后才在范围内。在您的特定情况下,返回类型(无论是否为延迟返回类型)始终是声明符的一部分。

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

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

    话虽如此,您仍然会遇到障碍,因为即使您使用lazy_enable_if_c,您仍然急切地计算qget&lt;I - 1&gt;() 的类型(作为lazy_enable_if_c 的参数),即使I0。懒惰地评估所述类型的身份不会拯救你。

    不幸的是,我似乎无法获得使用 GCC 4.7.2 运行的示例,即使将条件固定为 I &gt; 0 并使用惰性结果,它也坚持不终止递归(尽管通常我会使用 4.8) ,所以我不能向你保证我的解决方案可以奏效。

    【讨论】:

    • 感谢卢克的非常清楚的解释。我通常也会使用struct,但在这个简化的示例中,我试图探索这条途径作为替代方案。我想我很乐意使用泛型/库结构/类(如enable_if),但这次我宁愿避免使用定制的struct 路由。我会等待以防出现解决方案,但您已经回答了问题。
    猜你喜欢
    • 1970-01-01
    • 2022-12-25
    • 2015-04-02
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 2015-09-06
    • 1970-01-01
    相关资源
    最近更新 更多