【发布时间】:2023-01-27 22:39:14
【问题描述】:
我有一个 Foo 类,它可以由 C 风格的字符串、字符串视图和非临时字符串构造(实际上它包含其他成员和方法,并且它以字符为模板传递给 basic_string*s 模板) :
struct Foo {
explicit constexpr Foo()
: text{}
{}
explicit constexpr Foo(std::string_view text)
: text{std::move(text)}
{}
explicit constexpr Foo(char const* text)
: Foo{std::string_view{text}}
{}
explicit constexpr Foo(char* text)
: Foo{std::string_view{text}}
{}
explicit constexpr Foo(std::string&&) = delete;
std::string_view text;
};
在 Boost.Hana 的帮助下,出于文档目的,我可以断言 Foo 可以由什么构建,什么不能,在测试中:
for_each(make_basic_tuple(
type_c<std::string>,
// clearly I'm not also listing type_c<int> and all the countless imaginable types that wouldn't work
type_c<std::string&&>
),
[](auto t){
static_assert(!std::is_constructible_v<Foo, typename decltype(t)::type>);
});
for_each(make_basic_tuple(
type_c<char*>,
type_c<char const*>,
// ...
type_c<std::string_view>,
type_c<std::string const&>
),
[](auto t){
static_assert(std::is_constructible_v<Foo, typename decltype(t)::type>);
});
但是通过 Boost.Hana,也定义了一个 make_line 辅助函数:
namespace boost::hana {
template <>
struct make_impl<Foo> {
static constexpr Foo apply(const char* text) {
return Foo{text};
}
static constexpr Foo apply(std::string const& text) {
return Foo{text};
}
static constexpr Foo apply(std::string_view text) {
return Foo{std::move(text)};
}
static constexpr Foo apply(std::string&&) = delete;
};
}
inline constexpr auto make_foo = boost::hana::make<Foo>;
我可以很容易地验证它只适用于参数的预期类别值:
make_foo("");
make_foo(""sv);
make_foo(sv);
make_foo(s);
//make_foo(std::move(s)); // correctly doesn't compile
//make_foo(""s); // correctly doesn't compile
但是,我无法通过 hana::is_valid 在测试中编写此代码。这是我失败的尝试:
std::string s{};
std::string_view sv{};
constexpr auto can_make_foo_from =
is_valid([](auto&& obj) -> decltype(make_foo(std::forward<decltype(obj)>(obj))){});
static_assert( decltype(can_make_foo_from(""))::value);
static_assert( decltype(can_make_foo_from(""sv))::value);
static_assert( decltype(can_make_foo_from(sv))::value);
static_assert( decltype(can_make_foo_from(s))::value);
//static_assert(!decltype(can_make_foo_from(std::move(s)))::value);
//static_assert(!decltype(can_make_foo_from(""s))::value);
在我的意图中,最后两行应该编译,但它们没有。
【问题讨论】:
标签: c++ c++17 template-meta-programming sfinae boost-hana