Используйте концепции или 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>;
};

Дополнительный вопрос

Кроме того, я не понимаю, почему приведенный выше пример не работает.

1 ответ

Есть ли способ написать это, чтобы гарантировать, что 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>;
};

ДЕМО.

Обратите внимание, что это не отклонит тип, который перегружает send с помощью функции, не являющейся шаблоном, и функции шаблона: оба являются жизнеспособными кандидатами в разрешении перегрузки, перегрузка без шаблона может быть лучшим кандидатом (учитывая обычные правила разрешения перегрузки).

Другие вопросы по тегам