https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124617

            Bug ID: 124617
           Summary: meta::extract fails (or ICEs) for static member
                    function templates of class templates
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

This example (sorry I tried to reproduce, but couldn't, see below) fails to be
a constant expression due to the meta::extract call throwing — saying I got the
type wrong. But the type is correct, and the constexpr output (incredible!)
seems to just not substitute the types into the static member function template
(https://compiler-explorer.com/z/qboM8shM1):

#include <array>
#include <meta>

template <class T, class U>
struct Variant {
    union {
        T t;
        U u;
    };
    int index;

    constexpr Variant(T t) : t(t), index(0) { }
    constexpr Variant(U u) : u(u), index(1) { }

    template <int I> requires (I < 2)
    constexpr auto get() const -> auto const& {
        if constexpr (I == 0) return t;
        else if constexpr (I == 1) return u;
    }
};

#ifdef __clang__
#define __builtin_constexpr_diag(...)
#endif

template <class R, class F, class V0, class V1>
struct binary_vtable_impl {
    template <int I, int J>
    static constexpr auto visit(F&& f, V0 const& v0, V1 const& v1) -> R {
        return f(v0.template get<I>(), v1.template get<J>());
    }


    static constexpr auto get_array() {
        return std::array{
            std::array{^^visit<0, 0>, ^^visit<0, 1>},
            std::array{^^visit<1, 0>, ^^visit<1, 1>}
        };
    }

    using Ptr = decltype(&visit<0, 0>);

    // This constexpr variable will be initialized to
    // an array of pointers to consteval functions.
    static constexpr std::array fptrs = get_array();
};

template <class R, class F, class V0, class V1>
constexpr auto visit(F&& f, V0 const& v0, V1 const& v1) -> R {
    using Impl = binary_vtable_impl<R, F, V0, V1>;
    auto which = Impl::fptrs[v0.index][v1.index];
    __builtin_constexpr_diag(0, "aa", display_string_of(type_of(which)));
    __builtin_constexpr_diag(0, "bb", display_string_of(dealias(^^typename
Impl::Ptr)));
    auto func = std::meta::extract<typename Impl::Ptr>(which);
    return func((F&&)f, v0, v1);
}

struct Plus {
    consteval auto operator()(auto x, auto y) const {
        return x + y;
    }
};

consteval auto func(const Variant<int, long>& v1, const Variant<int, long>& v2)
{
    return visit<int>(Plus{}, v1, v2);
}

static_assert(func(Variant<int, long>{42}, Variant<int, long>{1729}) == 1771);


-------


I attempted to reduce the example to this:

#include <meta>

template <class T>
struct S {
  template <class U>
  static void f() {}

  static constexpr auto p = ^^f<int>;
};

constexpr void (*p)() = extract<void(*)()>(^^S<int>::p);

which ICEs: 

<source>: In instantiation of 'constexpr std::meta::info S<int>::p':
<source>:11:43:   required from here
   11 | constexpr void (*p)() = extract<void(*)()>(^^S<int>::p);
      |                         ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
<source>:8:31: internal compiler error: in filter_memfn_lookup, at
cp/pt.cc:17940
    8 |   static constexpr auto p = ^^f<int>;
      |                               ^
0x2967e18 diagnostics::context::diagnostic_impl(rich_location*,
diagnostics::metadata const*, diagnostics::option_id, char const*,
__va_list_tag (*) [1], diagnostics::kind)
        ???:0
0x295ca5b internal_error(char const*, ...)
        ???:0
0xb22cf4 fancy_abort(char const*, int, char const*)
        ???:0
0xdd1f5d instantiate_decl(tree_node*, bool, bool)
        ???:0
0xc3e0a3 maybe_instantiate_decl(tree_node*)
        ???:0
0xc3e0ef decl_constant_var_p(tree_node*)
        ???:0
0xb8fb79 cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        ???:0
0xdf47f0 process_metafunction(constexpr_ctx const*, tree_node*, tree_node*,
bool*, bool*, tree_node**)
        ???:0
0xb9046c cxx_eval_constant_expression(constexpr_ctx const*, tree_node*,
value_cat, bool*, bool*, tree_node**)
        ???:0
0xba94a9 maybe_constant_value(tree_node*, tree_node*, mce_value)
        ???:0
0xe78937 store_init_value(tree_node*, tree_node*, vec<tree_node*, va_gc,
vl_embed>**, int)
        ???:0
0xc2fff6 cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int,
cp_decomp*)
        ???:0
0xd6f583 c_parse_file()
        ???:0
0xef9b29 c_common_parse_file()
        ???:0

Reply via email to