Pat*_*rts 5 c++ lambda decltype template-meta-programming c++20
在尝试创建一个玩具 DSL 时,我遇到了一个奇怪的构造,clang 和 gcc 都没有按照我预期的方式处理:
#include <utility>
template <class...>
struct disjunction {};
template <auto>
struct literal {};
template <class T, T Min, T Max>
using range = decltype([]<T... Cs>(std::integer_sequence<T, Cs...>) {
return disjunction<literal<T{Min + Cs}>..., literal<Max>>{};
}(std::make_integer_sequence<T, Max - Min>{}));
template <class T, T... Cs> requires (sizeof...(Cs) == 1)
constexpr literal<Cs...> operator""_c() { return {}; }
template <class T, T Min, T Max>
constexpr range<T, Min, Max> operator-(literal<Min>, literal<Max>) { return {}; }
constexpr auto digits = "0"_c - "9"_c;
using expected = const disjunction<
literal<'0'>, literal<'1'>, literal<'2'>, literal<'3'>, literal<'4'>,
literal<'5'>, literal<'6'>, literal<'7'>, literal<'8'>, literal<'9'>>;
static_assert(std::is_same_v<decltype(digits), expected>);
Run Code Online (Sandbox Code Playgroud)
在这里,clang 崩溃并且 gcc 计算为type 的digits值。0int
我设法使用部分模板专业化找到了以下解决方法:
namespace detail {
template <class, auto, auto> struct range;
template <class T, T... Cs, T Min, T Max>
struct range<std::integer_sequence<T, Cs...>, Min, Max> {
using type = disjunction<literal<T{Min + Cs}>..., literal<Max>>;
};
} // namespace detail
template <class T, T Min, T Max>
using range = typename detail::range<
std::make_integer_sequence<T, Max - Min>, Min, Max>::type;
Run Code Online (Sandbox Code Playgroud)
在这种情况下, 的实现range允许static_assert上述对于 clang 和 gcc 都成功,但是如果能够在没有类模板帮助器的情况下实现此模板那就太好了。
最后,在使用 的初始实现时range,如果表达式如下"0"_c - "9"_c所示decltype(...):
using digits = decltype("0"_c - "9"_c);
using expected = disjunction<
literal<'0'>, literal<'1'>, literal<'2'>, literal<'3'>, literal<'4'>,
literal<'5'>, literal<'6'>, literal<'7'>, literal<'8'>, literal<'9'>>;
static_assert(std::is_same_v<digits, expected>);
Run Code Online (Sandbox Code Playgroud)
然后 clang 不会崩溃或报告诊断信息,如此处static_assert 所示。然而,gcc 仍然失败,当检查实际类型时,digits如下所示:
template <class Type>
auto f() { static_assert(sizeof(Type) == 0); }
int main() { f<digits>(); }
Run Code Online (Sandbox Code Playgroud)
clang 再次崩溃
error: cannot compile this l-value expression yet
int main() { f<digits>(); }
^~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
最后一条错误消息似乎表明 clang 承认此构造格式良好,但我不确定。
正如标题所示,我想了解我尝试range使用decltype立即调用的 lambda 表达式的实现是否格式良好。
| 归档时间: |
|
| 查看次数: |
148 次 |
| 最近记录: |