【问题标题】:`boost::hana` introspection for templated function`boost::hana` 模板化函数的自省
【发布时间】:2018-04-10 14:03:50
【问题描述】:

我想知道一个类型是否定义了带有模板参数的成员函数,但模板参数受 SFINAE 约束。

例如我有一个类型 A 和一个函数 foo

struct A{
   template<typename T>
   std::enable_if<Condition<T>,ReturnType> foo(T t){ ... }
};

Condition 是一些条件,例如std::is_pos_v

现在我正在使用 boost::hana::is_valid 来确定一个类型是否具有像 foo()foo(int) 这样的成员函数,但是当使用模板参数时我迷路了。

我想写这样的东西

auto has_foo = hana::is_valid([](auto t) -> delctype(hana::traits::declval(t).foo(???)){});
has_foo(hana::type_c<A>); // <-- I want this to return true

问题是我应该放什么而不是???


编译器可能不可能“证明”类型A 满足:“对于满足Condition 的每个类型T,都有一个成员函数A::foo(T)

所以为了使编译器更容易,我很乐意至少“证明”对于类型 A 成立:“有一个类型 T 这样就有一个成员函数 A::foo(T)

不幸的是,这在我的示例中仍然很难,因为这需要证明存在满足 Condition 的类型。

因此,出于内省的目的,是否有可能忽略 SFINE?然后我可以选择任意类型并测试例如A::foo(int).

【问题讨论】:

  • 这听起来不可能。此外,如果该类型是特定的尚未实例化的类模板怎么办?
  • 为什么你想要这个高阶逻辑?您要解决的实际问题是什么?
  • @liliscent 是的,这可能是不可能的。无论如何,我正在使用 C++ 并尝试从类别理论中实现基本概念,例如不同类型的类别、函子、产品、总和、指数对象等。所以代码真的很通用,我想捕捉错误为尽快,否则错误消息将无法阅读。因此,所描述的问题就是我要解决的问题。
  • 或者我可以改写一下。我想确保给定的函数对象(struct A)确实是某个集合的映射(由Condition 给出)。 (对我来说,集合是 T 类型的值的集合,类型满足 Condition
  • @JasonRice 我添加了一个我想写的代码。

标签: c++ templates template-meta-programming introspection boost-hana


【解决方案1】:

如上所述,除了编写编译器插件和自己遍历 AST 之外,没有为这种内省提供任何工具。

如果你提供一个具体的T,你当然可以使用hana::is_valid来制作一个完整有效的表达式。

我提供了一个额外的示例,它允许提供一个“概念”,假设某种设施可以为您输入的任何“概念”提供具体的T。不过,这有点牵强。

#include <boost/hana.hpp>
#include <type_traits>
#include <utility>

namespace hana = boost::hana;
using hana::Sequence;


struct A {
    template <typename T>
    std::enable_if_t<Sequence<T>::value, void> foo(T) { }
};

struct B {
    template <typename T>
    void bar(T) { }
};


template <typename T>
auto has_foo_1 = hana::is_valid([](auto&& a)
    -> decltype(std::forward<decltype(a)>(a).foo(std::declval<T>())) { });


template <template <typename, typename> typename Concept>
auto declval_concept_impl = int{};

template <>
auto declval_concept_impl<Sequence> = hana::tuple<>{};

template <template <typename, typename> typename Concept>
using declval_concept = std::add_rvalue_reference_t<decltype(declval_concept_impl<Concept>)>;

template <template <typename, typename> typename Concept>
auto has_foo_2 = hana::is_valid([](auto&& a)
    -> decltype(std::forward<decltype(a)>(a).foo(declval_concept<Concept>{})) { });

int main() {
    A a;
    B b;

    static_assert(    has_foo_1<hana::tuple<>>(a));
    static_assert(not has_foo_1<hana::tuple<>>(b));
    static_assert(    has_foo_2<Sequence>(a));
    static_assert(not has_foo_2<Sequence>(b));
}

【讨论】:

  • 如果我理解正确,那么“提供具体T 的某种设施”您的意思是auto declval_concept_impl&lt;Sequence&gt; = hana::tuple&lt;&gt;{}; 对吗?在这个例子中有点傻,但我认为我可以看到潜力。
  • 是的,我认为工具选项听起来很现实。
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2017-08-21
  • 2022-01-12
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多