<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/86606>86606</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Template lambda mixing up types in some template contexts
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
joshuamaiche
</td>
</tr>
</table>
<pre>
Apologies for the slightly convoluted repro; the behavior seems to manifest when only certain templates are at play.
**main.cpp**
```
#include <type_traits>
template <typename... Ts>
struct TypeList
{
template <typename T>
static constexpr bool Contains()
{
return (std::is_same_v<T, Ts> || ...);
}
template <auto checker>
using evaluate_on_all_t =
std::integral_constant<bool,
(checker.template operator()<Ts>() || ...)>;
// Works fine
template <typename T>
static constexpr bool overlaps_v =
evaluate_on_all_t<
[]<typename U>(){return T::template Contains<U>();}
>::value;
// Fails to compile
template <typename T>
using overlaps_t =
evaluate_on_all_t<
[]<typename U>(){return T::template Contains<U>();}
>;
};
using MyTypeList = TypeList<float, int>;
constexpr bool TypeListOverlap_v = MyTypeList::overlaps_v<TypeList<int, bool>>; // Works fine
using TypeListOverlap_t = MyTypeList::overlaps_t<TypeList<int, bool>>; // Fails to compile
int main()
{}
```
The relevant parts here are `overlaps_v` and `overlaps_t`. Both use a template lambda to evaluate if a TypeList `T` contains any relevant types. In the case of `overlaps_v`, a template constexpr variable, `T` is correctly interpreted as being a TypeList, and compiles. However, in the case of `overlaps_t`, a template alias, the compiler seems to get confused, and thinks `T` refers to the individual variadic types of the TypeList. Note that the lambdas are identical; the main difference seems to be whether a constexpr variable or an alias is being used.
**Console**
```
>clang++ -std=c++20 main.cpp
main.cpp:28:37: error: type 'float' cannot be used prior to '::' because it has no members
[]<typename U>(){return T::template Contains<U>();}
^
main.cpp:15:31: note: in instantiation of function template specialization 'TypeList<float, int>::(anonymous
class)::operator()<float>' requested here
(checker.template operator()<Ts>() || ...)>;
^
main.cpp:27:9: note: in instantiation of template type alias 'evaluate_on_all_t' requested here
evaluate_on_all_t<
^
main.cpp:33:36: note: in instantiation of template class 'TypeList<float, int>' requested here
constexpr bool TypeListOverlap_v = MyTypeList::overlaps_v<TypeList<int, bool>>; // Works fine
^
main.cpp:28:37: error: type 'int' cannot be used prior to '::' because it has no members
[]<typename U>(){return T::template Contains<U>();}
^
main.cpp:15:31: note: in instantiation of function template specialization 'TypeList<float, int>::(anonymous
class)::operator()<int>' requested here
(checker.template operator()<Ts>() || ...)>;
^
main.cpp:27:9: note: in instantiation of template type alias 'evaluate_on_all_t' requested here
evaluate_on_all_t<
^
main.cpp:33:36: note: in instantiation of template class 'TypeList<float, int>' requested here
constexpr bool TypeListOverlap_v = MyTypeList::overlaps_v<TypeList<int, bool>>; // Works fine
^
main.cpp:28:37: error: type 'int' cannot be used prior to '::' because it has no members
[]<typename U>(){return T::template Contains<U>();}
^
main.cpp:15:31: note: in instantiation of function template specialization 'TypeList<int, bool>::(anonymous
class)::operator()<int>' requested here
(checker.template operator()<Ts>() || ...)>;
^
main.cpp:27:9: note: in instantiation of template type alias 'evaluate_on_all_t' requested here
evaluate_on_all_t<
^
main.cpp:21:37: note: in instantiation of template class 'TypeList<int, bool>' requested here
[]<typename U>(){return T::template Contains<U>();}
^
main.cpp:33:48: note: in instantiation of static data member 'TypeList<float, int>::overlaps_v<TypeList<int, bool>>'
requested here
constexpr bool TypeListOverlap_v = MyTypeList::overlaps_v<TypeList<int, bool>>; // Works fine
^
main.cpp:28:37: error: type 'bool' cannot be used prior to '::' because it has no members
[]<typename U>(){return T::template Contains<U>();}
^
main.cpp:15:31: note: in instantiation of function template specialization 'TypeList<int, bool>::(anonymous
class)::operator()<bool>' requested here
(checker.template operator()<Ts>() || ...)>;
^
main.cpp:27:9: note: in instantiation of template type alias 'evaluate_on_all_t' requested here
evaluate_on_all_t<
^
main.cpp:21:37: note: in instantiation of template class 'TypeList<int, bool>' requested here
[]<typename U>(){return T::template Contains<U>();}
^
main.cpp:33:48: note: in instantiation of static data member 'TypeList<float, int>::overlaps_v<TypeList<int, bool>>'
requested here
constexpr bool TypeListOverlap_v = MyTypeList::overlaps_v<TypeList<int, bool>>; // Works fine
^
4 errors generated.
```
**version**
```
>clang++ --version
clang version 16.0.5
Target: i686-pc-windows-msvc
Thread model: posix
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWd1u47YSfhr6ZhBBpmzJufBF7CQ4BzinvXHRS2MkjS3uUqRKUk7cpy9IybLjOD-76HZ3iwiBbMnDmW---SMYtFZsFdGcTRdsejvC1lXazD9pW7VYoygqGuW63M9vGi31VpCFjTbgKgIrxbZycg-FVjstW0clGGqMZskiCORU4U5oA5aotuA01KjEhqyDh4oUaOUXk3EoFDiqG4mOLKAhQAeNxH3E4lsW3_R37v9qFCoqmqZ76n9J4_6vF0yEKmRbErBk6fYNrZ1B4SxL7k4VHkwepBTWFEURrI6C1pm2cLDaN_Q_YV2_Olt0XwAALimB1aAArEMnCs-RdfTYGMi1lrDUynttGZ8xfn3U9kS1vwy51ihgfGZdyZIbltwIu7ZY03rHkuWK8WWHF1i2ZNkSoijyGpPFqdLbU7fPUWPrNBQVFZ_JHHEDQGuF2gLtULboaK3VGqVcO2DJ7eDcAZNytDUo18FPVI4lS-8o48un_gQ8fNabiwYcuiGDTpuekGTZBSE8nbt2N3h34iO_Z_weftfms4WNUPT-CAG8ECS9IyOxsevdicvP6GDJJRdDNZ0a_G1wh2WLPqqrjrwB4JAVyfJEPFkMARzUew78Ug-GXqbjHoUMhVfouhHyQMo7GOliPzDgfkgGDm5nt2cUdOj_vz_UrUd_LOJkuZEanS8d4TP1qOksAQ4rfu1o6PLgRG0H_pgmPm2PRrxuvgyagg1v5qU87QCf23Ov23Pvt3c5Ebq7UA58Vz3tRb4PDV3jrLuG-6oiMCRph8pBg8ZZqMg3bkPA0viEkzQGVOWTl46lcQQL7SpoLQEeE1JinZfogR6yDMQGEI6BTOOVV1n0iQKo9kcgPtdsBP9VYf4UaAn05hkez9KJzWPQd2gE5pK8wMGQsFBoY6jwk863OdMY8qMOLeTko3ZEFxSr8kCyjeA_-oF2ZLpUexGUew4KpUDr34U1nb6TQbol53FvWkvlwaqrhPpsB-CGNmSCsFchVCl2omxRdl6WoujY8li8wMGHCH7RjsBV6ML7LiLdVBYlKScKlIcJ79MGSrHZkCFV0BFfTn7Eu4oM4AWCQRtA1TnpGe6I9M5cmPhLraz2QXl54Cd3hUS1ZXzB-AKuwli6LbpHHsOwZwjSw1Nyw2csuUkyltwAGaON_-JZAcazvkdkUKBS2nmXPEBojN_SOO1luoL0QjkV6HNZOKjQgtJQU52Tsf94Z3ztYtO7ZxyMp56DsXddaUf-UygQ3RgX6IRWPkc2rSrC9wGRbagQKMWfnQzj2WsdtiNqhkqrfa3bJ7wUEq0N7oT-dr4V6HR5nzMw9EdL1tefbze9kr9vQ3GRoRDn67cIGiyHBOpSm_Hs-bR8yYv-emW8XgKXJP6Wvhtd4PqNYL2A8LtNx8tReaV2g_Kfp3J_vLJ8oyJfz5Nvs9f_KM2P0vw3l-Y56x-V-e0qk4-HBP3qyjyL13sY_7E2fqE9TWZvkdCfjZTosC-_98yU9_cWnp268XM3t-7I6-fpbl-ZOd-1AYbrjS74VlF-9L6P3vfR-17vfV92DSRPuq5oYUvKF9TxSOfSMWJ3qLMjY4VWX3DCc3VY0pHkf4L-FYzTKI6m_TElmi25EN50ll41xdWDUKV-sFe13RWHo0xDWEKtS5JestFWPJ6hGJXzpLxOrnFE83E2Hk_GyWyajqp5lqQFpzS5no7zPJ6WWVrOeJleXyPPimmSjcScx3wSJzyN48lknEbTvOB5liZpmpUZ8Q2bxFSjkJGUuzrSZjsS1rY0n6VpnI4k5iRt-O8c54oeIPzIOGfT25GZ-zVXebu1bBJLYZ09anHCSZqvzk5Wa_EYjtqa_vRPKLC6pienoY4enR21Rs4r5xob2rDPka1wVZtHha4Zv_d2-o-rxuhPVDjG7wM6y_h9QP9XAAAA__8mZY69">