Enr*_*lis 6 c++ decltype sfinae comma-operator template-meta-programming
标题应该能澄清我的困惑。我想用这个问题来获得全面的答案,这有助于我理解逗号运算符如何decltype在 SFINAE 上下文中使用。我的这个问题中显示了一个示例用法。
搜索is:question [c++] [decltype] comma,可以找到以下 6 个问题:
\n(2011) How is decltype Should to work withoperator,有一个很有前途的标题,但它是 VisualStudio 特定的,并且唯一的答案从根本上声称编译器中确实存在错误。
(2012)如何从自动返回类型推导出类型?接受的答案如下,参考表达式decltype( ( bool( fun(v[0] ) ), void() ) ),
\n\n\n
\n- 该表达式实际上
\nbool( fun(v[0] ) )并未被求值,因为我们处于非求值上下文中(,类似于)。这里重要的是,如果整个表达式被求值,它将被求值,因此,如果子表达式无效,则整个表达式也无效。decltypesizeof- \n
void()并不是真正的值,但它的行为类似于逗号运算符和上下文中的值decltype。
我还没有真正理解。
\n(2014) c++11 decltype returns reference type没有详细说明,但接受的答案表达了i, j左值表达式的想法,因此decltype返回它的引用类型,所以如果我正确理解它本质上说可以是一个工具来禁用将被路由到的, 1特殊情况(如果是未加括号的...),非常类似于和周围。给出这个,我会问是否对.decltype(x)x()xdecltype((unparenthesized-name))decltype(unparenthesized-name, 0)unparenthesized-name
(2015)为什么我们不能在未评估的上下文中使用大括号初始值设定项?连同它的体内问题为什么我们不能用它void{}来代替?似乎有点无关,因为它主要是关于是否可以创建一个void价值。
(2015)SFINAE:static_cast<void>()或, void()?没有公认的答案,所以如果提问者对任何答案不满意,我相信他们的代表和徽章,而且我对这些答案也不满意。
(2020)如何使用 sfinae 排除定义函数的类型?似乎无关。
\n但我还没有理解完整的故事。
\n从cppreference我读到
\n\n\n在逗号表达式 中
\nE1, E2,对表达式E1进行求值,其结果被丢弃 ([\xe2\x80\xa6]),并且其副作用在表达式 E2 的求值开始之前完成 ([\xe2\x80\xa6])。逗号表达式结果的类型、值和值类别正是第二个操作数 的类型、值和值类别
\nE2。
所以我很想理解,就其中E1, E2出现的代码而言,唯一使表达式E1, E2与 just 不同的E2是 的副作用E1。
然而,该页面显然没有解决operator,inside的使用decltype。那么让我们看看decltype文档页面有什么内容:
\n\n该类型不需要是完整的或具有可用的析构函数,并且可以是抽象的。此规则不适用于子表达式: in
\ndecltype(f(g())),g()必须具有完整类型,但f()不一定。
(如果我错了,请纠正我,但我想这句话适用于整个点(2),而不仅仅是点(2.c)。另外,我假设最后一个指的f()是表达式。) f(g())
在我的这个问题下的评论中,@cigien评论说传递f(g())或f(), 0todecltype对返回类型强制执行相同的完整性要求f。
基于此,我推断这decltype(f(), 0)只是一种放置东西的方法std::void_t<>只是当我们想要时在 SFINAE 上下文中
f()格式良好,就像我们通过decltype(f()),decltype(f()).据我所知,这, 0只是我们用来作为 的f()第一个参数的一个技巧,。我们也可以这样做decltype(f(), f()),并且会强制执行相同的要求f;是的,decltype会导致返回类型为f而非int,但如果我们将该类型提供给 ,则这是无关紧要的std::void_t<>。
然而,至于整个逗号技巧,HolyBlackCat表示它并不稳健
\n\n\n因此,如果
\nbegin()有效并返回完整类型,但,已重载并且由于某种原因无法调用,您将得到漏报
(我对上述声明的演示)并提出decltype(void(std::declval<T>().begin()))了更好的替代方案。但这是如何运作的呢?为什么转换为void会触发比不转换更多的事情,即decltype(std::declval<T>().begin())?
通常要求纯右值具有完整类型 ([basic.lval]/9),而 for 的例外情况decltype仅适用于整个表达式 ([dcl.type.decltype]/2)。因此,将表达式强制转换为void对其类型施加完整性要求(如果不涉及引用);该特定操作的选择是由其通用性(任何内容都可以转换为void)和已知的结果类型驱动的。该结果可以直接与为支持此类 SFINAE 而引入的模板参数进行匹配class=void,或者可以,应用(这也需要完整性)而不必担心重载,以便为整个表达式选择一些其他固定类型。
| 归档时间: |
|
| 查看次数: |
433 次 |
| 最近记录: |