Closed
Description
We noticed this as code using sol2 failing to compile with clang 18. It was reported to that project here: ThePhD/sol2#1581 (also as duplicate ThePhD/sol2#1588).
It’s demonstrated by this reduced test case:
#include <type_traits>
template <typename T>
struct class_tmpl {
template <bool B> static int call_e() { return 0; }
template <bool B> static int call_ne() noexcept { return 0; }
template <bool B> static int call() noexcept(std::is_nothrow_copy_assignable<T>::value) { return 0; }
};
int main(int argc, char *argv[])
{
using function_ptr = int (*)();
function_ptr f1 = &class_tmpl<int>::call_e<false>;
function_ptr f2 = &class_tmpl<int>::call_ne<false>;
function_ptr f3 = &class_tmpl<int>::call<false>;
return 0;
}
With clang 18 (including clang 18.1), compilation fails with -std=c++14
or -std=c++17
with the following error:
test.cpp:15:24: error: address of overloaded function 'call' does not match required type 'int ()'
15 | function_ptr f3 = &class_tmpl<int>::call<false>;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:7:34: note: candidate template ignored: substitution failure [with B = false]
7 | template <bool B> static int call() noexcept(std::is_nothrow_copy_assignable<T>::value) { return 0; }
| ^
1 error generated.
When the noexcept
specification uses an expression that depends on the class template arguments, clang reports a substitution failure. The code compiles with clang 17 and earlier, as far back as clang 6 at least.