c++ - 返回模板化实体的函数的概念

标签 c++ c++20 c++-concepts

我一直在尝试向 constexpr json parser 添加概念并且正在努力定义正确的 Parser概念。我的第一次尝试:

using parse_input_t = std::string_view;
template <typename T>
using parse_result_t = std::optional<std::pair<T, std::string_view>>;

// A parser for type `T` is a function: parse_input_t -> parse_result_t<T>
template <typename F, typename T>
concept Parser = std::is_invocable_r_v<parse_result_t<T>, F, parse_input_t>;

问题是我想用签名编写函数:

template <Parser P>
auto func(P p);

也就是说,我不要T在界面中。

我可以用一些丑陋的东西来完成我想要的:

template <typename F>
concept Parser = requires(F f, parse_input_t i)
{
    requires requires(typename decltype(f(i))::value_type result)
    {      
        { f(i) } -> std::same_as<parse_result_t<decltype(result.first)>>;
    };
};

有没有更干净的方法来做到这一点?我希望是这样的:

template <typename F>
concept Parser = requires(F f, parse_input_t i)
{
    { f(i) } -> std::same_as<parse_result_t<auto>>;
};

最佳答案

当然,你可以这样做。

定义一个类型特征来拉出 T来自 std::optional<std::pair<T, std::string_view>> :

template <typename T>
struct parser_type;
template <typename T>
struct parser_type<std::optional<std::pair<T, std::string_view>>> {
    using type = T;
};
template <typename T>
using parser_type_t = typename parser_type<T>::type;

围绕试图拉出 T 的类型特征定义一个类型特征。从您调用 F 开始:
template <typename F>
using parser_result = parser_type_t<std::invoke_result_t<F, std::string_view>>;

并围绕它建立一个概念:
template <typename F>
concept Parser = requires {
    typename parser_result<F>;
};

然后您可以使用 parser_result<F>作为解析器的关联类型。例如:

struct Ints {
    auto operator()(std::string_view) -> std::optional<std::pair<int, std::string_view>>;
};

static_assert(Parser<Ints>);
static_assert(std::same_as<int, parser_result<Ints>>);

关于c++ - 返回模板化实体的函数的概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62094857/

相关文章:

c++ - std::bit_cast 和 std::start_lifetime_as 之间有什么有用的区别吗?

c++ - 约束类模板函数以接受特定的 POD 类型

c++ - 使用 C++ 在两个排序数组中查找匹配值索引的最有效方法

c++ - 扩展最初在内联命名空间的封闭命名空间中定义的内联命名空间中的命名空间

c++ - 是否可以将运算符用作映射中的映射值?

c++ - 为什么 std::derived_from 概念是通过添加 cv 限定符的附加可转换性测试来实现的?

c++ - 概念检查器无法在 gcc 上编译,因为它是 'has no linkage'

c++ - 实现C++ 20 bidirectional_iterator概念

c++ - 如何使用字符串的值将字符串转换为 wstring?

c++ - 使用 gcc c++ 获取 Windows 版本