【问题标题】:SFINAE for expressions and decltype(auto)表达式和 decltype(auto) 的 SFINAE
【发布时间】:2013-08-29 12:19:43
【问题描述】:

我可以将 SFINAE 用于表达式和 decltype auto 混合吗?

template<class T>
auto function() -> decltype(typename trait<T>::test(), auto) {
  return [](){ return T(); };
}

【问题讨论】:

  • decltype(a, b) 应该是什么意思?
  • @StefanoFalasca 表达式(a, b) 使用内置命令运算符。它评估a,丢弃结果,然后评估b。所以decltype(a, b) 的类型与decltype(b) 相同,但a 必须是有效的表达式
  • decltype(a,b) 是 decltype(expr)。在表达式中,您可以使用逗号运算符执行多项操作,例如在for(expr; expr; expr) 你可以写for(...; ...; ++i, ++j) 来增加两个索引;表达式的返回类型是最后一个表达式的返回类型,在本例中为decltype(b)。
  • @JoachimPileborg,我回滚了你的错误编辑,自动返回类型的扣除是c++1y而不是c++11
  • 糟糕,我刚刚注意到我在上面的第一条评论中输入了“命令运算符”,我的意思是 comma 运算符,但我的手指显然不想停止输入

标签: sfinae c++14


【解决方案1】:

不,我认为你不能。

语法不允许:

decltype-specifier:
decltype(表达式)
decltypedecltype(auto)

decltype(expr, auto) 不是有效的decltype-specifier,而decltype(auto) 是有效的,并且它作为占位符类型具有特殊含义。措辞非常具体:

使用 auto 或 decltype(auto) 声明的变量的类型是从其初始化程序推导出来的 [...] auto 或 decltype(auto) 应作为 decl-specifiers 之一出现在 decl-specifier-seq decl-specifier-seq 后面应该跟一个或多个 init-declarators,每个 init-declarators 都应该有一个非空的初始化器。

在 C++17 中,Concepts Lite 无论如何都应该使此类 SFINAE hack 变得不必要,因此我们不必永远依赖它们。您可以修改您的示例以将 SFINAE 约束放在默认模板参数中:

template<class T, class Requires = decltype(typename trait<T>::test())>
auto function() -> decltype(auto) {
  return [](){ return T(); };
}

【讨论】:

  • 是的,我正在使用虚拟模板参数和decltype 或EnableIf/DisableIf。感谢您的精彩回答!
  • Concepts Lite 无法进入 C++14?
  • @TemplateRex,不,C++14 的内容已经固定,不包括 Concepts Lite。计划制定一个涵盖概念的单独技术规范。详情请见isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013-meeting。
【解决方案2】:

您可以将默认模板参数 SFINAE 与函数返回类型推导一起使用。

template<class T, class = decltype(typename trait<T>::test())>
auto function() {
  return [](){ return T(); };
}

缺点是您没有可用的参数名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    • 2021-11-18
    相关资源
    最近更新 更多