将对模板化函数的引用封装在编译时对象中

encapsulate reference to templated function inside compile time object

截至撰写本文时,metaclasses 很遗憾还不是一项功能。

我正在尝试将对模板化函数的引用封装在一些编译时对象中,理想情况下编译时对象很容易制作,类似于带有 consteval ctor 的类型。

使用非模板函数 ptr 执行此操作很简单:

template <typename T>
struct Magma { //magma trait

    T (& combine)(T, T);

    consteval Magma(decltype(combine) c): combine{c} {}
};

template <typename T, const Magma<T> & mag>
T add(T x, T y) {return mag.combine(x, y);}

这是一个天真的尝试使用模板函数 ptr 的示例:

template <template<typename> typename F>
struct Functor { //functor trait

    template <typename A, typename B> //member template compilation error
    F<B> (& map)(std::function<B(A)>, F<A>);

    consteval Functor(decltype(map) m): map{m} {}
};

//...

template <template<typename>typename F, const Functor<F> & ftor>

这失败了,因为在成员模板的情况下,遗憾的是没有办法告诉编译器该类型只在编译时存在,而不是(在写作时)它会关心。

我遇到的问题:

最后的想法

我现在看不到这样做的方法,我相信这需要 C++ 允许显式编译时间类型,其数据成员签名与模板 args 相匹配。

如果有人知道封装此行为的方法,请留下答案,或者如果您有任何问题,请发表评论。

I could write Functor as a concept and have "instances" of Functor be classes with visible static member functions with matching name and signature; but that makes the "instances" obtuse to implement.

通常是这样完成的。它是 一点 笨拙的,尽管它与 haskell 中在 rust 或类型类中完成特征的方式并没有什么不同。如果你想实现 haskell Functor 例如:

template<template<typename> typename T>
struct Functor : public std::false_type {};

template<>
struct Functor<std::vector> : public std::true_type {
    template<typename T, typename F>
    requires (std::invocable<F, T>)
    static auto fmap(std::vector<T> v, F&& f) -> std::invoke_result_t<F, T> {
        // ...
    }
};

template<template<typename> typename C, typename T, typename F>
requires (Functor<C>::value && std::invocable<std::remove_cvref_t<F>, T>)
auto fmap(C<T> v, F&& f) {
    return Functor<C>::fmap(v, std::forward<F>(f));
}

这让您可以简单地使用它 fmap 为您提供编译时多态性,同时仍然允许类似实现的特征。实际上,您还应该制定一个概念来指定 Functor 实现的要求并使用它而不是仅仅检查任何实现(使用 value