Используйте концепции или 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 с помощью функции, не являющейся шаблоном, и функции шаблона: оба являются жизнеспособными кандидатами в разрешении перегрузки, перегрузка без шаблона может быть лучшим кандидатом (учитывая обычные правила разрешения перегрузки).