SFINAE and decltype(auto)

20
如果一个函数模板使用decltype(auto)(或者其他使用auto的类型说明符)做为返回值,但是该函数的return语句不符合要求,那么是否会发生SFINAE?return语句被认为是函数签名的直接上下文吗?
N3690草案中似乎没有要求这一点。默认情况下,我认为SFINAE不适用。
这似乎很不幸,因为您可以编写一个函数来转发到另一个函数,但您不能使其存在取决于委托方,就像长手写一样。此外,如果没有decltype(auto),则无法检查对等非静态成员函数的存在,因为this不能在函数签名中使用。然而,这表明了一个根本性问题,decltype(auto)提供了一种将类类型视为完整的路径,在成员签名中,这是不正确的。
是否有提案被撰写或者问题已被正式分析过?
将类类型视为完整的能力在成员签名中可能具有其他影响...但这只是另一个问题的素材。

我一直在想这个问题。可悲的是,我也太懒了,没有跟进1年的提案... - sehe
@MarkGarcia 是的,这是肯定的。我只是在问题的末尾添加了一个注意事项;非模板成员仍可能打开通往暮光区的虫洞。 - Potatoswatter
如果问题中有一些示例,对像我这样的蠢货来说理解起来会更容易。 :) - iammilind
一个小例子会更有助于让问题更清晰。也许还有其他实现你想要的方法。 - n. m.
@n.m. 总有更多的方法。我并没有卡住,但我正在尝试避免有8个重复的过载。我要找的答案是一个指向提案文件的指针,这样我就可以知道是否要自己撰写报告。 - Potatoswatter
2个回答

17
但是返回语句将不合法,会导致SFINAE吗? 提案-n3638 表示,
“SFINAE”
由于返回类型是通过实例化模板来推导的,因此“如果实例化无效,则会导致错误而不是替换失败”。这允许auto函数返回lambda,而使用decltype(返回表达式)模式则不可能。
希望这就是您要找的内容。

1
太棒了!正是我在寻找的东西。我现在得走了,但稍后我会阅读它,看看他们如何将成员实例化与不完整类型相调和。 - Potatoswatter

4

在Nawaz提供的链接中,其余问题可以在N3690 §7.1.6.4/11中找到答案:

如果需要确定表达式的类型,则需要使用具有未推导占位符类型的实体的类型,程序就无法形成。

这意味着即使SFINAE与返回类型推断一起使用,也不能用于查询一个函数声明是否与另一个函数相同。只有在处理return语句时,即在class {}定义的结束括号处,并且在已处理前面成员的定义之后,才能有效检查签名。

从某种意义上说,所有成员的decltype(auto)函数都不完整,相对于同一类中的先前函数而言:

struct s {
    void f() { a(); } // error: use of ‘auto s::a()’ before deduction of ‘auto’
    auto a() { return 3; }
};

这是GCC的投诉;如果成员声明被颠倒,问题就会消失。这是因为函数定义按照声明顺序处理,当到达类定义中的 } 符号时。如果在 return 3; 语句之前处理语句 a();,则程序不符规范。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接