C++20 中立即调用的 lambda 表达式的 decltype 格式正确吗?

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 表达式的实现是否格式良好。