[llvm-bugs] [Bug 44833] New: deleted functions in requires clauses don't SFINAE in concepts

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Feb 7 12:07:27 PST 2020


https://bugs.llvm.org/show_bug.cgi?id=44833

            Bug ID: 44833
           Summary: deleted functions in requires clauses don't SFINAE in
                    concepts
           Product: clang
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: C++2a
          Assignee: unassignedclangbugs at nondot.org
          Reporter: llvm at marehr.dialup.fu-berlin.de
                CC: blitzrakete at gmail.com, erik.pilkington at gmail.com,
                    llvm-bugs at lists.llvm.org, richard-llvm at metafoo.co.uk

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 https://godbolt.org/z/tyeiJ2 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.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200207/ad82851a/attachment.html>


More information about the llvm-bugs mailing list