<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/58353>58353</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Clang incorrectly instantiates class during CTAD
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
tinloaf
</td>
</tr>
</table>
<pre>
Consider this C++17 code, which compiles fine with GCC but fails with Clang (at least Clang 9 to Clang 15). It is an MWE that I condensed from GCC's STL implementation of `std::pair` and demonstrates a problem of calling `std::pair`'s constructor with a function:
```c++
#include <type_traits>
template <typename _T1>
struct _PCC
{
template <typename _U1>
static constexpr bool ConstructibleFrom()
{
return std::is_constructible<_T1, const _U1&>::value;
}
};
template<class T1>
struct MyContainer
{
T1 t1;
using _PCCP = _PCC<T1>;
template<class U1 = T1, typename
std::enable_if<_PCCP::template
ConstructibleFrom<U1>(),
bool>::type=true>
constexpr MyContainer(const T1& newT1) : t1(newT1) {}
};
template<typename T1> MyContainer(T1) -> MyContainer<T1>;
void someFunc() {};
int main()
{
auto c = MyContainer(someFunc);
}
```
What *should* happen here (I think) is that the constructor of `MyContainer` is *not* taken for CTAD. Taking the constructor for CTAD would lead to `T1` being deduced as `void()`, because `T1` is taken as a const reference in the constructor, which prevents function-to-pointer decay when deducing the template parameter for the constructor. But, if `T1` is deduced as `void()`, the `std::enable_if` disables the constructor - so it sholud not be taken for deduction.
The deduction guide below remains, and since `_T1` is taken by value there, function-to-pointer decay happens and `T1` is deduced as `void(*)()`. With `T1` deduced as `void(*)()`, `MyContainer` should be fine, since a function pointer can of course be a member.
However, Clang reports this error:
```
<source>:17:8: error: data member instantiated with function type 'void ()'
T1 t1;
^
<source>:21:24: note: in instantiation of template class 'MyContainer<void ()>' requested here
std::enable_if<_PCCP::template
^
<source>:24:15: note: while substituting prior template arguments into non-type template parameter [with T1 = void (), U1 = void ()]
constexpr MyContainer(const T1& newT1) : t1(newT1) {}
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:34:14: note: while substituting deduced template arguments into function template '<deduction guide for MyContainer>' [with T1 = void (), U1 = (no value), $2 = (no value)]
auto c = MyContainer(someFunc);
^
1 error generated.
```
I assume that this error arises because Clang tries to instantiate `MyContainer<void()>` *during CTAD*, more precisely while checking if the `std::enable_if` is satisfied or not. The locations reported in the error point to that, and: If you remove the `using` declaration from the class and instead write the constructor like this, the error goes away:
```c++
template<class U1 = T1, typename
std::enable_if<_PCC<T1>::template
ConstructibleFrom<U1>(),
bool>::type=true>
constexpr MyContainer(const T1& newT1) : t1(newT1) {}
```
Note that this is the same constructor as above, I just manually replaced `_PCCP` with `_PCC<T1>` and removed the `using`.
I assume that Clang somehow needs to instantiate the class (which is impossible with `T1 = void()`) for accessing the `using`, which is a member of the class.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzdWNtu2zgQ_Rr5hYhhSb7ED35I5WY3wHZRYF30MaAk2mYji1qSitd_v2dI3XxJmz4UC6xhOLbEuZ2ZOTNKqvLTKlGlkbnQzO6lYUkQfcA7XLBM5SKIEnbcy2yPX4dKFsKwrSwFO0q7Z78lCUtry7ZcFsZfSgpe7lgQ3XPLCsGNba4smVXN13AWRMsxe7IM1njJPn39CMs4_wQbZS5KI3K21epA-oNoYdhfmz-YPFSFOIjScitVydSWBfOJsXkQP-BdcanxG-pylosDArKaWzjLWaVVCkmSyHhRSHLvWtLZyZxcnVmlfTScbesyI4N0eLIOJu0nJNw782g1V6NYlllR54IFcWJPlXiGG9KaIP44lLYCwcC99lTJD4I9b8LumPeCPX8GAF5u0ZqYLG9LfwkHRpaGYMp8QOKfSrNUqYIlbXwSiDwCYeQJueikhlbw1sLWumQdVNI8Z0MNsE9Oo0LcZedDNCc33PFXXtQ4c6ZyYGrdRrYenBmiA_VZwY1h18B8OiEUy1GIml0AxPDahMyGF1rpem0o-4TqZ4C39vjGidcfDxRcufAldAI-2hb0LhjmXx1QuAt4nuWWECJr_nKn9QwQkr5OTJz4hPoERUnv280XpbcDnvyDt1AoOuDoUF8NA_xgwWePYpuzUhzpyxLhPhCI0X1_BRAv1qToHZnrCtOBe2HQ67u7vHGZieHnq5I5M-ogHtGQHpXGoYvjsrTsAH3tmevq4DWoKHP5PHerV7_slXZ12nb80NhXoq0gejB7VRc5vrA9rxA42wstiAWfiFPLF_IEZOdYzu7FGdF4Jht6Ah7DYWgrlSWdlr9A5RZnk83Desw2_IXq-FJRe4AdyRli35xIF-oAK3SmgqRykdcZCJYbukOwNjVGHAg6FxmvjeilyG1nnxOZ-lLRYov4ykwwWV660Q-MSotX8LXpOPTOqrtKIUHo2hx2TjgIxc6jNqCO3CquUT50lOK6MDJmH2pLluT2zNMfBEdahtzf9ynEc2nol7nC9Q51x6RlSDKonSEpQGmQFGeU4hsPS2MDLd0dtqsxYCFWqCPQo_o05BCNK3BS5tx6vgA8PTFHoeSQdoP4bSB92Rmn8B2APDhSaZAZs6806zqx98iQN9dV69uA0KEdgc744Poxylq3M-5meKZqbQgYnDmIQyr0GYi_qyNqyNWU3x20qJS2xm8qQmvUW3w5kpufcWKgPBOeFsMFPu6J1FoplnPbGkUdY2KWVqLycj_6O4-JydCMC8dALR8v3ho2DR8Hs4833YhC-piSedSRoL9ood56s9p0XeCnD-yd8-TQFxoSCwDzdy0Mee-K5da0-Lnx9Oao-X58FBoWvEF8IINCMFOnxkpbW2r0Skvq6TZIrnf1wTEFakNBEAVOoN_ggmD2wWVn4-fxWU6SdkoPr87Wv2z-XSOy-E_ft_IRu3xMf5CPtuPfykjfC93qiQ6Ik0t-IzY8K1RXmu_KGQGtPN81N4JoGt26NczoT43y2wUcekJgOwFJav_xd-b9E0jRAJl2krckBMCkwehop6cnK6sljRM1ZJdL1vS93LcyWBRUm9ea8kLT3BFvwg4KCwUmagY7xalJYrYXmVsFMAa_O9vgpwG5mK1EluEuagFrBCQKlTnSMQ2z4nYz0n1cjq4pBAq4mVhURE9bdlI1jTL1Klrbbr32EwS8pT2buQc5N1IdldGAIjhoOTlqacXVuC3ki3DQthO7yY-ip7kjP10T_tkz2C9Y3_vF9P-4xd-q8z-VHda49EuRoX1-mCpaCVMUAKH6xL7VhlbvssZT9onqqeBEKrTZuCGDwjg2i8YZqs1ju6-l_LKYxrc6z_cXNfkeC1UpRH7VZ33JIXq_kFIkh0oZQ_npfBnQ0mC9WToy41kmjGl304FX_ZZL_8Notwi17c2OR2IVzuezRTyZz-ejfBXny3jJRyDdQqx8AFiOlEZPW-A18N00jg9YYFTrYrW3tjJUHNEj3jv4X6fjjJ7iH4vitf1zV2n1DTrxUwIygT56nN3Hs3i0X6V8lqf381kWz7JZmMbpJN3m03meLsJ5mvPlqODYUc0KlA2eHclVNImicBJOJwhkOh9nEEmX93wyE3wyjaJgOqFlthiT4bHSu5FeOR_Semdws5DGmv4mgpI7ZKvVD_reK73CDCoU346cuyvn678HzJjK">