<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - deleted functions in requires clauses don't SFINAE in concepts"
href="https://bugs.llvm.org/show_bug.cgi?id=44833">44833</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>deleted functions in requires clauses don't SFINAE in concepts
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>C++2a
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>llvm@marehr.dialup.fu-berlin.de
</td>
</tr>
<tr>
<th>CC</th>
<td>blitzrakete@gmail.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>Sorry for this verbose and hard to read code, but I wanted to make this
configurable.
This code basically has multiple code paths. If REQUIRES_BUG is set, the impl
function uses requires to infer if char_is_valid_for is defined or not. If not
impl uses SFINAE.
```c++
#include <utility>
// #define REQUIRES_BUG 1 - enable the requires bug, 0 - disable it
// #define FUNCTION_DEFINED 1 - define function char_is_valid_for, 0 - do not
define char_is_valid_for
template <int I> struct priority_tag : priority_tag<I - 1> {};
template <> struct priority_tag<0> {};
struct alphabet_base {};
#if FUNCTION_DEFINED
using expect_return_type = bool;
bool char_is_valid_for(char, alphabet_base) { return true; };
#else
using expect_return_type = int;
#endif
namespace seqan3::detail::adl_only {
template <typename...> void char_is_valid_for(...) = delete;
template <typename alph_t>
struct char_is_valid_for_fn
{
using s_alph_t = alph_t;
#if REQUIRES_BUG
template <typename t>
static decltype(auto) impl(priority_tag<1>, t v)
requires requires { (char_is_valid_for(v, s_alph_t{})); }
{ return (char_is_valid_for(v, s_alph_t{})); }
#else
template <typename t>
static auto impl(priority_tag<1>, t v)
-> std::enable_if_t<true, decltype(char_is_valid_for(v, s_alph_t{}))>
{ return (char_is_valid_for(v, s_alph_t{})); }
#endif
template <typename t, typename = void>
static decltype(auto) impl(priority_tag<0>, t v) { return 0; }
};
} // namespace seqan3::detail::adl_only
int main() {
auto a =
seqan3::detail::adl_only::char_is_valid_for_fn<alphabet_base>::impl(priority_tag<1>{},
char{});
static_assert(std::is_same_v<decltype(a), expect_return_type>);
}
```
As you can see on <a href="https://godbolt.org/z/tyeiJ2">https://godbolt.org/z/tyeiJ2</a> when defining `clang++
-std=c++2a -DREQUIRES_BUG=1 -DFUNCTION_DEFINED=0` the requires block should
silently see that the requires is not valid (because of a deleted function) and
skip to the next definition.
Error Message:
```
<source>:31:15: error: call to deleted function 'char_is_valid_for'
{ return (char_is_valid_for(v, s_alph_t{})); }
^~~~~~~~~~~~~~~~~
<source>:45:75: note: in instantiation of function template specialization
'seqan3::detail::adl_only::char_is_valid_for_fn<alphabet_base>::impl<char>'
requested here
auto a =
seqan3::detail::adl_only::char_is_valid_for_fn<alphabet_base>::impl(priority_tag<1>{},
char{});
^
<source>:20:29: note: candidate function [with $0 = <>] has been explicitly
deleted
template <typename...> void char_is_valid_for(...) = delete;
^
<source>:45:8: error: variable has incomplete type 'void'
auto a =
seqan3::detail::adl_only::char_is_valid_for_fn<alphabet_base>::impl(priority_tag<1>{},
char{});
^
2 errors generated.
```
Interestingly, if you substitute `s_alph_t` with `alph_t;` everything works as
expected.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>