【问题标题】:How to detect if a generic lambda is uncompilable in C++ 14?如何检测通用 lambda 在 C++ 14 中是否不可编译?
【发布时间】:2015-09-30 20:17:53
【问题描述】:

我在检测通用 lambda 的实例何时格式正确但不可编译时遇到了问题,并且检测它让我很困惑:

#include <functional>

class future
{
public:
  int get() & { return 5; }
};

// Gets the return type of F(A), returning a not_well_formed type if not well formed
template<class F, class A> struct get_return_type
{
  struct not_well_formed {};
  template<class _F, class _A> static not_well_formed test(...);
  template<class _F, class _A> static auto test(_F &&f) noexcept(noexcept(f(std::declval<_A>()))) -> decltype(f(std::declval<_A>()));
  using type = decltype(test<F, A>(std::declval<F>()));
  static constexpr bool is_noexcept = noexcept(test<F, A>(std::declval<F>()));
};

int main(void)
{
  auto foo=[](auto &&x) { return x.get(); };
  using type=get_return_type<decltype(foo), const future>::type;
  return 0;
}

这失败了(在 clang 3.7 上):

ned@kate:~$ clang++-3.7 -std=c++14 -o weird_generic_lambda_thing weird_generic_lambda_thing.cpp 
weird_generic_lambda_thing.cpp:21:34: error: member function 'get' not viable: 'this' argument has type 'const future', but
      function is not marked const
  auto foo=[](auto &&x) { return x.get(); };
                                 ^
weird_generic_lambda_thing.cpp:14:111: note: in instantiation of function template specialization 'main()::(anonymous
      class)::operator()<const future>' requested here
  ..._F, class _A> static auto test(_F &&f) noexcept(noexcept(f(std::declval<_A>()))) -> decltype(f(std::declval<_A>()));
                                                                                                  ^
weird_generic_lambda_thing.cpp:15:25: note: while substituting explicitly-specified template arguments into function
      template 'test'
  using type = decltype(test<F, A>(std::declval<F>()));
                        ^
weird_generic_lambda_thing.cpp:22:14: note: in instantiation of template class 'get_return_type<(lambda at
      weird_generic_lambda_thing.cpp:21:12), const future>' requested here
  using type=get_return_type<decltype(foo), const future>::type;
             ^
weird_generic_lambda_thing.cpp:6:7: note: 'get' declared here
  int get() & { return 5; }
      ^
1 error generated.

您可能会在这里责怪我对 Expression SFINAE 的缺乏经验(感谢 Visual Studio!),但我很惊讶:如果 f(std::declval&lt;_A&gt;()) 格式不正确,创建 test() 的返回类型的 decltype 肯定不能替换吗?

显然,答案是确实无法替代,但以非 SFINAE 方式。如果泛型 lambda 无法使用某些任意参数类型编译,是否可以修复上述问题以便正确返回 not_well_formed 类型?

【问题讨论】:

  • 您的 lambda 需要声明为 auto foo = [](auto &amp;&amp;x) -&gt; decltype(x.get()) { return x.get(); }; 才能使其成为 SFINAEable

标签: c++ c++11 lambda c++14 sfinae


【解决方案1】:

一般情况下你不能。通过 SFINAE 只能检测到早期故障。早期失败基本上是函数(或类)模板的声明,而不是定义。

lambda 可以通过显式声明返回类型 -&gt;decltype(x.get()) 或通过其他 SFINAE 技术(如 enable_if_tvoid_t)来提供 SFINAE 早期故障检测。

这个想法是编译器不需要完全编译函数来进行重载解析。

【讨论】:

  • 嗯,那你会学到一些新东西。感谢您的快速回答。
猜你喜欢
  • 2015-07-17
  • 1970-01-01
  • 2013-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
相关资源
最近更新 更多