noexcept说明符神秘地破坏了编译

noexcept说明符神秘地破坏了编译

本文介绍了noexcept说明符神秘地破坏了编译(clang,gcc表示不同意)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有问题的代码是

#include <functional>
#include <utility>

template <typename F>
void for_each(F&&) noexcept {}

template <typename F, typename T, typename... Us>
void for_each(F&& f, T&& v, Us&&... us) {
  std::invoke(std::forward<F>(f), std::forward<T>(v));
  for_each(std::forward<F>(f), std::forward<Us>(us)...);
}

void func(void*) noexcept {}

int main() {
  for_each(func, nullptr);
}

它在 gcc 8 上编译,但在铛6 并显示以下错误:

It compiles on gcc 8, but fails on clang 6 with the following error:

/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4198:19: error: invalid application of 'sizeof' to a function type
    static_assert(sizeof(_Tp) > 0, "Type must be complete.");
                  ^~~~~~~~~~~
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4203:15: note: in instantiation of template class 'std::__1::__check_complete<void (void *) noexcept>' requested here
    : private __check_complete<_Tp>
              ^
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4496:15: note: in instantiation of template class 'std::__1::__check_complete<void (&)(void *) noexcept>' requested here
    : private __check_complete<_Fp>
              ^
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4559:9: note: in instantiation of template class 'std::__1::__invokable_r<void, void (&)(void *) noexcept, nullptr_t &&>' requested here
        __invokable<_Fp, _Args...>::value,
        ^
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4568:14: note: in instantiation of template class 'std::__1::__invoke_of<void (&)(void *) noexcept, nullptr_t &&>' requested here
    : public __invoke_of<_Fp, _Args...>
             ^
/opt/wandbox/clang-6.0.0/include/c++/v1/type_traits:4573:22: note: in instantiation of template class 'std::__1::result_of<void (&(nullptr_t &&))(void *) noexcept>' requested here
template <class _Tp> using result_of_t = typename result_of<_Tp>::type;
                     ^
/opt/wandbox/clang-6.0.0/include/c++/v1/functional:2349:1: note: in instantiation of template type alias 'result_of_t' requested here
result_of_t<_Fn&&(_Args&&...)>
^
prog.cc:9:3: note: while substituting deduced template arguments into function template 'invoke' [with _Fn = void (&)(void *) noexcept, _Args = <nullptr_t>]
  std::invoke(std::forward<F>(f), std::forward<T>(v));
  ^
prog.cc:16:3: note: in instantiation of function template specialization 'for_each<void (&)(void *) noexcept, nullptr_t>' requested here
  for_each(func, nullptr);
  ^
1 error generated.

删除func()上的noexcept说明符

void func(void*) /* noexcept */ {}

然后编译.我不明白这一点.这是编译器错误吗?

It then compiles. I don't get this. Is this a compiler bug?

推荐答案

好. libc ++无法处理标记为noexcept的函数.当函数为noexcept时,它的机器似乎由于某种原因而失败,并且采用了错误的部分专业化(针对对象而不是针对函数).

Well no. libc++ fails to handle noexcept marked functions. It looks like its machinery fails for some reason when the function is noexcept and it takes the wrong partial specialization (the one for objects not for functions).

因为您不能使用函数的sizeof,所以clang正确地抱怨了(gcc也会抱怨).

As you cannot take the sizeof of a function, clang rightly complains (and gcc would too).

作为一种解决方法,传入一个函数指针:

As a workaround, pass in a function pointer:

for_each(&func, nullptr);

我填写了一个错误报告,该问题已修复! :)

I filled a bug report, which was fixed! :)

这篇关于noexcept说明符神秘地破坏了编译(clang,gcc表示不同意)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 12:17