首页 > 解决方案 > 使用概念或 SFINAE 检查类是否具有带有 std::array 参数的模板化成员函数

问题描述

介绍

我想使用概念和/或类型特征来检测一个类是否具有带有 std::array 参数的成员函数。

例如:下面的类将传递这个概念。

class OStreamRealizationGood
{
    template<size_t size>
    uint8_t send(std::array<uint8_t, size> array)
};

到目前为止,我使用了一个概念技巧。诀窍是将大小定义为 0。所以我的概念如下所示:

template<typename Candidate>
concept OStream = requires(Candidate candidate, std::array<uint8_t, 0> array)
{
    {candidate.send(array)} -> std::same_as<uint8_t>;
};

这个技巧适用于模板函数,但它并不是我真正需要的东西。这不是我需要的东西,因为下面的课程也会遵守,但我希望它不需要。

class OStreamRealizationBad
{
    uint8_t send(std::array<uint8_t, 0> array)
};

问题

有没有办法写这个来确保它send(array)是一个模板化的函数?

我尝试过的事情

我有一个使用declval(size_t)如下图的想法,但这不适用于原始类型。

template<typename Candidate>
concept OStream = requires(Candidate candidate, std::array<uint8_t, declval(size_t)> array)
{
    {candidate.send(array)} -> std::same_as<uint8_t>;
};

另一个不起作用的想法是递归概念:

template<typename Candidate, size_t size>
concept HasSendImpl = requires(Candidate candidate, std::array<uint8_t, size> array)
{
    {candidate.send(array)} -> std::same_as<uint8_t>;
};

template<typename Candidate>
concept HasSend = requires(size_t size)
{
        requires HasSendImpl<Candidate, size>;
};

附加问题

另外,我不明白为什么上面的例子不起作用。

标签: c++arraysmetaprogrammingtypetraitsc++-concepts

解决方案


有没有办法写这个来确保它send(array)是一个模板化的函数?

您可以template在约束中使用关键字来表示send需要是模板函数:

template<typename T, std::size_t size>
concept GoodRealization = requires(T t, std::array<uint8_t, size> array) {
    { t.template send<size>(array) } -> std::same_as<uint8_t>;
};

演示

请注意,这不会拒绝使用非模板和模板函数重载发送的类型:两者都是重载决议的可行候选者,非模板重载可能是最佳候选者(鉴于重载决议的常规规则)。


推荐阅读