Closed
Description
Bugzilla Link | 44833 |
Version | trunk |
OS | Linux |
CC | @CaseyCarter,@erichkeane,@friedkeenan,@h-2,@JohelEGP,@AlexeyDmitriev,@PiliLatiesa,@zygoloid,@saarraz,@HighCommander4,@jwakely |
Extended Description
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.
#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.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
No status