Sam*_*ett 1 c++ boost sfinae c++14 boost-hana
我有一个模板函数,默认情况下没有定义,但它由某些类型专门化:
template <typename T>
auto foo(bar &, const T &) -> void;
template <>
auto foo<std::string>(bar &, const std::string &) -> void {}
Run Code Online (Sandbox Code Playgroud)
如何编写constexpr函数,告诉我类型T是否具有上述函数的特化?
我尽力而为:
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>());
Run Code Online (Sandbox Code Playgroud)
然而,这个静态断言会触发,如果我说得对,我希望它不会发生.
这里的问题是你将hana::types 传递给一个需要实际对象的函数.当你写作时detail::has_foo(type_c<bar>, type_c<T>),Hana按hana::type_c原样传递detail::has_foo.但由于foo不能用hana::types 调用,它失败了.相反,你有两个选择.第一个选择是继续传递hana::types detail::has_foo,但要declval 在内部 使用has_foo(注意我已经添加了适当的ref-qualifiers到bar和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>(), "");
Run Code Online (Sandbox Code Playgroud)
另一种选择是完全放弃使用hana::type并将实际对象传递给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 {}; }
Run Code Online (Sandbox Code Playgroud)
在这里,我正在使用std::declval- 如果我有正确类型的对象,然后我调用detail::has_foo那些"对象".你选择哪一个主要是偏好问题.此外,根据您的使用情况,您可能在调用时可以使用实际对象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(bar& b, T const& t) -> decltype(detail::has_foo(b, t)) { return {}; }
Run Code Online (Sandbox Code Playgroud)
通过在常量表达式中删除lambdas禁令,C++ 17将使我们的生活更轻松,这将允许您编写
constexpr auto has_foo = hana::is_valid([](bar& b, auto const& t) -> decltype(foo(b, t)) { });
Run Code Online (Sandbox Code Playgroud)
因此无需外部助手.
另外请注意,你并非专门测试是否foo有专业化的T,但真正能否foo(...)很好地形成表达.在存在重载或ADL时,这可能会略有不同,但对于大多数用例来说应该足够了.我不确定是否可以精确检查某个功能是否专用于某种类型.
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
739 次 |
| 最近记录: |