Boost.Hana:如何检查函数是否具有特定类型的专门化? [英] Boost.Hana: How to check if function has specialisation for a certain type?

查看:72
本文介绍了Boost.Hana:如何检查函数是否具有特定类型的专门化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板函数,默认情况下没有定义,但是它由某些类型专用:

I have a template function that has no definition by default but it specialised by some types:

template <typename T>
auto foo(bar &, const T &) -> void;

template <>
auto foo<std::string>(bar &, const std::string &) -> void {}

我该如何编写constexpr函数来告诉我T类型是否具有上述函数的专业化?

How do I write a constexpr function that tells me if type T has a specialisation for the above function?

我最大的努力:

namespace detail {

auto has_foo(hana::is_valid([](auto &b, const auto &t) -> decltype(foo(b, t)) {}));

} // namespace detail

template <typename T>
constexpr auto has_foo() -> bool
{
  using hana::type_c;

  return detail::has_foo(type_c<bar>, type_c<T>);
}

static_assert(has_foo<std::string>());

但是,此静态断言会触发,如果我理解正确,我希望不会触发该断言.

This static assert fires, however, which I would expect it not to if I had got this right.

推荐答案

此处的问题是您要将hana::type s传递给需要实际对象的函数.当您编写detail::has_foo(type_c<bar>, type_c<T>)时,Hana将hana::type_c的原样传递给detail::has_foo.但是由于foo不能用hana::type调用,所以它失败了.相反,您有两个选择.第一种选择是继续将hana::type s传递给detail::has_foo,但是要使用declval inside has_foo(请注意,我已经在bar中添加了适当的ref限定词,并且T):

The problem here is that you're passing hana::types to a function that expects actual objects. When you write detail::has_foo(type_c<bar>, type_c<T>), Hana passes the hana::type_cs as-is to detail::has_foo. But since foo can't be called with hana::types, it fails. Instead, you have two options. The first option is to keep on passing hana::types to detail::has_foo, but to use declval inside has_foo (note that I have added the proper ref-qualifiers to bar and T):

#include <boost/hana.hpp>
#include <string>
namespace hana = boost::hana;


struct bar { };

template <typename T>
auto foo(bar&, T const&) -> void;

template <>
auto foo<std::string>(bar&, std::string const&) -> void { }

namespace detail {
    auto has_foo = hana::is_valid([](auto b, auto t) -> decltype(
        foo(hana::traits::declval(b), hana::traits::declval(t))
    ) { });
}

template <typename T>
constexpr auto has_foo() -> bool {
  return detail::has_foo(hana::type_c<bar&>, hana::type_c<T const&>);
}

static_assert(has_foo<std::string>(), "");

另一种选择是完全放弃使用hana::type并将实际对象传递给detail::has_foo:

The other option is to drop the usage of hana::type altogether and to pass actual objects to detail::has_foo:

namespace detail {
    auto has_foo = hana::is_valid([](auto& b, auto const& t) -> decltype(foo(b, t)) { });
}

template <typename T>
constexpr auto has_foo() -> decltype(
    detail::has_foo(std::declval<bar&>(), std::declval<T const&>())
) { return {}; }

在这里,如果我有正确类型的对象,我将使用std::declval进行操作,然后使用这些对象"调用detail::has_foo.您选择哪一个主要是偏好问题.另外,根据您的用例,当您调用has_foo时,实际的对象也许可用.在这种情况下,您可以重构为

Here, I'm using std::declval to do as-if I had objects of the proper type, and then I call detail::has_foo with those "objects". Which one you pick is mainly a matter of preference. Also, depending on your use case, perhaps the actual objects are available when you call has_foo. If this is the case, you could refactor to

namespace detail {
    auto has_foo = hana::is_valid([](auto& b, auto const& t) -> decltype(foo(b, t)) { });
}

template <typename T>
constexpr auto has_foo(bar& b, T const& t) -> decltype(detail::has_foo(b, t)) { return {}; }

C ++ 17消除了常量表达式中对lambda的禁止,这使我们的生活更加轻松

C++17 will make our life much easier by removing the ban on lambdas in constant expressions, which will allow you to write

constexpr auto has_foo = hana::is_valid([](bar& b, auto const& t) -> decltype(foo(b, t)) { });

因此无需外部帮助程序.

thus removing the need for an external helper.

还要注意,您不是专门测试foo是否具有T专业化,而是实际上是测试foo(...)表达式是否格式正确.在存在重载或ADL的情况下,这可能会有所不同,但是对于大多数用例而言,这应该足够了.我不确定是否可以精确检查某个函数是否专门用于某种类型.

Also note that you're not specifically testing whether foo has a specialization for T, but really whether the foo(...) expression is well-formed. This can be subtly different in the presence of overloads or ADL, but it should be sufficient for most use cases. I'm not sure if it's possible to precisely check whether a function is specialized for some type.

希望这会有所帮助!

这篇关于Boost.Hana:如何检查函数是否具有特定类型的专门化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆