templated QueryInterface
От: The Passenger Голландия  
Дата: 11.02.20 09:23
Оценка:
Понадобилось тут создать базовый для IUnknown ... тянуть ATL было лень
стал смотреть в сторону статической типизации на шаблонах, нашел такое —

https://www.codeproject.com/Tips/1057327/Variadic-Template-Technique-and-COM-Unusual-Soluti

Можно ли сделать с 14 или 17 плусами это поэлегантнее — без разбивки на 2 функции для вариадик и невариадик?

к стати — как эта техника ( разбиения ) ( паттерн ) называется?
Весь мир — Кремль, а люди в нем — агенты
Отредактировано 11.02.2020 9:42 The Passenger . Предыдущая версия .
Re: templated QueryInterface
От: rg45 СССР  
Дата: 11.02.20 11:30
Оценка: 2 (1)
Здравствуйте, The Passenger, Вы писали:

TP>Понадобилось тут создать базовый для IUnknown ... тянуть ATL было лень

TP>стал смотреть в сторону статической типизации на шаблонах, нашел такое —
TP>https://www.codeproject.com/Tips/1057327/Variadic-Template-Technique-and-COM-Unusual-Soluti

TP>Можно ли сделать с 14 или 17 плусами это поэлегантнее — без разбивки на 2 функции для вариадик и невариадик?


Как по мне, то и так достаточно элегантно — одна функция обепечивает рекурсивный перебор, другая представляет собой обработчик одной итерации. Можно обе задачи поместить в один скоуп, но все равно вторую функцию прийдется оставить как тривиальное замыкание рекурсии:

      template<typename Interface, typename... Args>         
      bool castInterfaces(             
           REFIID aRefIID,             
           _COM_Outptr_ void __RPC_FAR *__RPC_FAR *aPtrPtrVoidObject,             
           Interface* aThis,             
           Args... aRest)         
      {             

         if (aThis && aRefIID == __uuidof(Interface))
         {                 
             *aPtrPtrVoidObject = aThis;
             return true; 
         }
         return castInterfaces(aRefIID, aPtrPtrVoidObject, aRest...);             
     }
        
     bool castInterfaces(             
          REFIID aRefIID,             
          _COM_Outptr_ void __RPC_FAR *__RPC_FAR *aPtrPtrVoidObject)         
    {             
        return false;
    }
};
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.02.2020 11:37 rg45 . Предыдущая версия . Еще …
Отредактировано 11.02.2020 11:33 rg45 . Предыдущая версия .
Отредактировано 11.02.2020 11:32 rg45 . Предыдущая версия .
Re: templated QueryInterface
От: night beast СССР  
Дата: 11.02.20 11:31
Оценка: 2 (1)
Здравствуйте, The Passenger, Вы писали:

TP>https://www.codeproject.com/Tips/1057327/Variadic-Template-Technique-and-COM-Unusual-Soluti


TP>Можно ли сделать с 14 или 17 плусами это поэлегантнее — без разбивки на 2 функции для вариадик и невариадик?


что именно в данном решении не устраивает?
вторая функция нужна для завершения обхода.
ее можно сделать без аргументов, всегда возвращающую фалсе.
можно поставить проверку в
if constexpr(sizeof...(Args) > 0)
но не уверен, что это будет боле наглядно.
Re[2]: templated QueryInterface
От: rg45 СССР  
Дата: 11.02.20 11:51
Оценка: 6 (1) +1
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, The Passenger, Вы писали:


TP>>Понадобилось тут создать базовый для IUnknown ... тянуть ATL было лень

TP>>стал смотреть в сторону статической типизации на шаблонах, нашел такое —
TP>>https://www.codeproject.com/Tips/1057327/Variadic-Template-Technique-and-COM-Unusual-Soluti

TP>>Можно ли сделать с 14 или 17 плусами это поэлегантнее — без разбивки на 2 функции для вариадик и невариадик?


R>Как по мне, то и так достаточно элегантно — одна функция обепечивает рекурсивный перебор, другая представляет собой обработчик одной итерации. Можно обе задачи поместить в один скоуп, но все равно вторую функцию прийдется оставить как тривиальное замыкание рекурсии:


Впрочем, здесь можно было бы заюзать fold expressions (C++17) и запихнуть все в одну функцию таким образом (не компилил):

      template<typename... Interfaces>         
      bool castInterfaces(             
           REFIID aRefIID,             
           _COM_Outptr_ void __RPC_FAR *__RPC_FAR *aPtrPtrVoidObject,             
           Interfaces*... interfaces)         
      {             
         auto checkInterface = [&](auto* aThis)
         {
           if (aThis && aRefIID == __uuidof(decltype(*aThis)))
           {                 
             *aPtrPtrVoidObject = aThis;
             return true; 
           }
           return false;
         };
         return (checkInterface(interfaces) || ...);             
     }
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.02.2020 12:45 rg45 . Предыдущая версия . Еще …
Отредактировано 11.02.2020 11:55 rg45 . Предыдущая версия .
Отредактировано 11.02.2020 11:54 rg45 . Предыдущая версия .
Отредактировано 11.02.2020 11:52 rg45 . Предыдущая версия .
Re[2]: templated QueryInterface
От: The Passenger Голландия  
Дата: 11.02.20 11:59
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, The Passenger, Вы писали:


TP>>https://www.codeproject.com/Tips/1057327/Variadic-Template-Technique-and-COM-Unusual-Soluti


TP>>Можно ли сделать с 14 или 17 плусами это поэлегантнее — без разбивки на 2 функции для вариадик и невариадик?


NB>что именно в данном решении не устраивает?

NB>вторая функция нужна для завершения обхода.
NB>ее можно сделать без аргументов, всегда возвращающую фалсе.
NB>можно поставить проверку в
NB>if constexpr(sizeof...(Args) > 0)
NB>но не уверен, что это будет боле наглядно.

я думал может както фолдинг можно прикрутить
Весь мир — Кремль, а люди в нем — агенты
Re[2]: templated QueryInterface
От: The Passenger Голландия  
Дата: 11.02.20 11:59
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, The Passenger, Вы писали:


TP>>Понадобилось тут создать базовый для IUnknown ... тянуть ATL было лень

TP>>стал смотреть в сторону статической типизации на шаблонах, нашел такое —
TP>>https://www.codeproject.com/Tips/1057327/Variadic-Template-Technique-and-COM-Unusual-Soluti

TP>>Можно ли сделать с 14 или 17 плусами это поэлегантнее — без разбивки на 2 функции для вариадик и невариадик?


я думал может както фолдинг можно прикрутить
Весь мир — Кремль, а люди в нем — агенты
Re[3]: templated QueryInterface
От: rg45 СССР  
Дата: 11.02.20 12:04
Оценка:
Здравствуйте, The Passenger, Вы писали:

TP>я думал может както фолдинг можно прикрутить


Уже: http://rsdn.org/forum/cpp.applied/7655250.1
Автор: rg45
Дата: 11.02.20
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: templated QueryInterface
От: night beast СССР  
Дата: 11.02.20 12:07
Оценка: +1 :)
Здравствуйте, rg45, Вы писали:

TP>>я думал может както фолдинг можно прикрутить


R>Уже: http://rsdn.org/forum/cpp.applied/7655250.1
Автор: rg45
Дата: 11.02.20


но от доп функции избавиться все равно не получилось
Re[3]: templated QueryInterface
От: rg45 СССР  
Дата: 12.02.20 11:19
Оценка:
Здравствуйте, rg45, Вы писали:

R>Впрочем, здесь можно было бы заюзать fold expressions (C++17) и запихнуть все в одну функцию таким образом (не компилил):



Да, на всякий случай. Для того, чтобы корректно обрабатывался пустой список интерфейсов, вид fold-expression нужно слегка изменить:

    return (checkInterface(interfaces) || ... || false);



[Upd] Был неправ. Объяснение ниже по ветке: http://rsdn.org/forum/cpp.applied/7660136.1
Автор: _NN_
Дата: 17.02.20
.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 17.02.2020 15:52 rg45 . Предыдущая версия . Еще …
Отредактировано 17.02.2020 15:51 rg45 . Предыдущая версия .
Отредактировано 17.02.2020 15:49 rg45 . Предыдущая версия .
Отредактировано 12.02.2020 11:19 rg45 . Предыдущая версия .
Re[4]: templated QueryInterface
От: _NN_ www.nemerleweb.com
Дата: 17.02.20 15:16
Оценка: 16 (1)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, rg45, Вы писали:


R>>Впрочем, здесь можно было бы заюзать fold expressions (C++17) и запихнуть все в одну функцию таким образом (не компилил):


R>Да, на всякий случай. Для того, чтобы корректно обрабатывался пустой список интерфейсов, вид fold-expression нужно слегка изменить:


R>
R>    return (checkInterface(interfaces) || ... || false);             
R>


https://en.cppreference.com/w/cpp/language/fold

When a unary fold is used with a pack expansion of length zero, only the following operators are allowed:
1) Logical AND (&&). The value for the empty pack is true
2) Logical OR (||). The value for the empty pack is false
3) The comma operator (,). The value for the empty pack is void()

Нет проблемы с пустым списком. Просто вернёт false.
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.