【问题标题】:decltype(auto), trailing return type and sfinae: can we mix them?decltype(auto)、尾随返回类型和 sfinae:我们可以混合使用它们吗?
【发布时间】:2016-09-28 06:31:06
【问题描述】:

考虑以下代码:

auto f() -> decltype(auto) { /* do whatever you want here */ }
int main() { f(); }

推导出返回类型,decltype(auto) 用作尾随返回类型。
下面的代码是稍作修改(实际上是sfinae'd)的版本:

struct S { static void f() {} };
struct T {};

template<typename U>
auto f(int) -> decltype(U::f(), void()) {
    // do whatever you want here
}

template<typename>
auto f(char) -> decltype(auto) {
    // do whatever you want here
}

int main() {
    f<S>(0);
    f<T>(0);
}

如果你参加考试这个功能:

template<typename U>
auto f(int) -> decltype(U::f(), void()) {
    // do whatever you want here
}

问题是:是否可以使用尾随返回类型进行 sfinae 并且仍然推导出返回类型?
我的意思是类似于下面的代码(当然,这是行不通的):

template<typename U>
auto f(int) -> decltype(U::f(), auto) {
    // do whatever you want here
}

注意:我不是在寻找涉及模板参数的替代方法,我知道它们,我只是想知道 this 是否是一个可行的解决方案。

【问题讨论】:

  • 不认为这是可能的,但您是否希望将类型推断为autodecltype(auto)
  • 别以为你可以在这里做任何事。推导的返回类型故意不 SFINAE。
  • @Holt 好问题,我会像第一个例子一样说decltype(auto),但如果你知道如何将它推导出为auto,它也是一个很好的答案。跨度>

标签: c++ templates language-lawyer sfinae decltype


【解决方案1】:

decltype(auto) 是一个不可分割的结构(几乎就像是decltype_auto 这样的关键字)。除此之外,auto 不能在 decltype(x) 中用作独立实体,因为这会阻止 x 成为有效表达式。

【讨论】:

    【解决方案2】:

    您可以向函数添加另一个 void(*)() 类型的参数,并将带有尾随返回类型的 lambda 作为默认参数分配给它,以便可以通过 lambda 应用 SFINAE:

    template<typename U>
    decltype(auto) f(int, void(*)() = []()->decltype(U::f(), void()) {})
    {
        // do whatever you want here
    }
    

    【讨论】:

      【解决方案3】:

      不是答案,而是使用 void_t 的可能解决方法。

      至少它和你想做的一样干燥:

      template<typename... Ts> struct make_void { typedef void type;};
      template<typename... Ts> using void_t = typename make_void<Ts...>::type;
      
      
      struct S { static int f() { return 3; } };
      struct P { static int p() { return 4; } };
      struct T {};
      
      template<typename U, void_t<decltype(U::f())>* = nullptr >
      auto f(int) -> decltype(auto)
      {
          // do whatever you want here
          std::cout << "f1\n";
          return U::f();
      }
      
      template<typename U, void_t<decltype(U::p())>* = nullptr >
      auto f(int) -> decltype(auto)
      {
          // do whatever you want here
          std::cout << "f3\n";
          return U::p();
      }
      
      template<typename>
      auto f(char) -> decltype(auto) {
          std::cout << "f2\n";
          // do whatever you want here
      }
      
      int main() {
          std::cout << f<S>(0) << '\n';
          std::cout << f<P>(0) << '\n';
          f<T>(0);
      }
      

      【讨论】:

        猜你喜欢
        • 2017-08-02
        • 2019-09-09
        • 2017-01-25
        • 1970-01-01
        • 2011-11-07
        • 2023-03-04
        • 2017-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多