#c #c 20 #c -concepts
Вопрос:
Вероятно, проще всего конкретно описать то, что я пытаюсь решить, чтобы это было легче понять.
У меня есть SmartPointer
концепция, так что у меня могут быть функции, которые могут принимать или std::unique_ptr
std::shared_ptr
:
template lt;typename Tgt; concept SmartPointer = requires(const Tamp; t) { requires std::same_aslt;decltype(t.get()), typename T::pointergt;; };
Я хочу создать функцию, которая может принимать пару итераторов, где тип значения итератора должен иметь тип SmartPointer
, и мне не нужно явно определять какие-либо типы.
Я могу создать функцию, которая имеет параметр шаблона с ограничением SmartPointer, и проверить это:
template lt;SmartPointer T, std::forward_iterator TIterator, std::sentinel_forlt;TIteratorgt; TIteratorSentinelgt; requires std::same_aslt;std::iter_value_tlt;TIteratorgt;, Tgt; void doWithSmartPointers(TIterator begin, TIteratorSentinel end) { for (auto it = begin; it != end; it) { // Some logic with it-gt;get() etc. } }
Однако при его использовании от меня требуется явно указать T
, чего я бы предпочел не делать:
std::vectorlt;std::unique_ptrlt;intgt;gt; v{}; v.push_back(std::make_uniquelt;intgt;(1)); v.push_back(std::make_uniquelt;intgt;(2)); v.push_back(std::make_uniquelt;intgt;(3)); doWithSmartPointer(v.begin(), v.end()); // Error, couldn't infer template argument T doWithSmartPointlt;std::unique_ptrlt;intgt;gt;(v.begin(), v.end()); // OK
Из сообщения об ошибке я предполагаю, что мне нужно какое-то руководство по дедукции шаблонов, но, насколько я вижу, они могут быть определены только для классов/структур, а не функций.
По сути, я хочу чего-то подобного:
template lt;std::forward_iterator TIterator, std::sentinel_forlt;TIteratorgt; TIteratorSentinelgt; requires std::same_aslt;std::iter_value_tlt;TIteratorgt;, SmartPointergt; // Not valid syntax! void doWithSmartPointers(TIterator begin, TIteratorSentinel end) { for (auto it = begin; it != end; it) { // Some logic with it-gt;get() etc. } }
Правильно ли я поступаю в этом вопросе? Возможно ли это вообще? Заранее благодарю вас!
Комментарии:
1. В стороне: обычно вам не нужно использовать
get
интеллектуальный указатель,-gt;
он вычисляется рекурсивно
Ответ №1:
Вам не нужен T
параметр шаблона:
template lt; std::forward_iterator TIterator , std::sentinel_forlt;TIteratorgt; TIteratorSentinel gt; requires SmartPointerlt; std::iter_value_tlt;TIteratorgt; gt; // ^^^^^^^^^^^^ void whatever(TIterator begin, TIteratorSentinel end) { // ... }
Комментарии:
1. Ах, блестяще, спасибо! Я думал, что это должно быть возможно 🙂
Ответ №2:
Если у вас много таких шаблонных функций whatever
, возможно, стоит определить концепцию «итератора, указывающего на интеллектуальный указатель».
template lt;typename Tgt; concept SmartPointerIterator = requires std::forward_iteratorlt;Tgt; amp;amp; SmartPointerlt;std::iter_value_tlt;Tgt;gt;; template lt; SmartPointerIterator TIterator , std::sentinel_forlt;TIteratorgt; TIteratorSentinel gt; void whatever(TIterator begin, TIteratorSentinel end) { // ... }