Description
Minimal reproducible example
template <class... Ts>
struct Type_list {
private:
template <int index, class... Args>
struct Get_at;
template <class T, class... Args>
struct Get_at<0, T, Args...> {
using Type = T;
};
template <int index, class T, class... Args>
struct Get_at<index, T, Args...> {
using Type = typename Get_at<index - 1, Args...>::Type;
};
public:
template <int index>
using at = typename Get_at<index, Ts...>::Type;
constexpr static auto size = sizeof...(Ts);
};
template <class F>
struct CI {};
template <class R, class... PArgs>
struct CI<R (*)(PArgs...)> {
using Args = Type_list<PArgs...>;
};
template <class Function>
constexpr bool is_viable_source = []<class Properties_list>(Properties_list) {
if constexpr (Properties_list::size != Properties_list::size) {
static_assert(false);
return sizeof(typename CI<Function>::Args::template at<0>) > 0;
}
return false;
}(Type_list<>{});
int main() {
return is_viable_source<void (*)()>;
}
https://godbolt.org/z/o3co4j31e
Expected behavior
Successfully builds executable equivalent to int main() {}
.
Actual behavior: Compilation error
<source>:17:2: error: implicit instantiation of undefined template 'Type_list<>::Get_at<0>'
17 | using at = typename Get_at<index, Ts...>::Type;
| ^
<source>:32:55: note: in instantiation of template type alias 'at' requested here
32 | return sizeof(typename CI<Function>::Args::template at<0>) > 0;
| ^
<source>:29:78: note: while substituting into a lambda expression here
29 | constexpr bool is_viable_source = []<class Properties_list>(Properties_list) {
| ^
<source>:38:9: note: in instantiation of variable template specialization 'is_viable_source<void (*)()>' requested here
38 | return is_viable_source<void (*)()>;
| ^
<source>:5:9: note: template is declared here
5 | struct Get_at;
| ^
1 error generated.
Affected versions
Clang 18, clang 19 and clang trunk
C++23 and above (it seems the explicit lambda template argument is required to reproduce, which is a C++23 feature)
Gcc compiles the code successfully.
Reasoning why clang is wrong
The error is caused by code inside an if constexpr
that evaluates to false
, thus clang should not have attempted to compile the code or ignored the error. Clang partially agrees that the if constexpr
evaluates to false
and that the code should not be compiled since it does not complain about the static_assert(false);
.
Workaround
The code compiles after replacing the immediately invoked lambda with a helper function: https://godbolt.org/z/6P5qToWWT
This also applies to my ungolfed code.