The code in question is
#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);
}
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.
Remove the noexcept
specifier on func()
void func(void*) /* noexcept */ {}
It then compiles. I don't get this. Is this a compiler bug?
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).
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! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With