Страницы

Поиск по вопросам

четверг, 15 ноября 2018 г.

Как наложить на вариардик ограничение по принимаемым типам?

Пусть есть такая конструкция:
template class SomeClass { template SomeClass(Args& ...args) {} };
Каким образом можно "уговорить" компилятор принимать в пакет только одинаковые типы, и как указать конкретный тип (пусть, например, double)?


Ответ

Вопрос решен
Помогло чтение "Язык программирования С++. Лекции и упражнения. 6-е издание, 2012 год, Сивен Пратта".
Методика, как оказалось, незатейлива - рекурсивная распаковка и чек каждого аргумента пака. Получилось два варианта, но со static_assert'ом, имхо, лучше - более осмысленный вывод. В качестве эксперимента проверяем агрументы на соответствие std::size_t.
Вариант 1 (static_assert):
#include #include #include
//////////////////////////////////////////////////////////////////// // Пример проверки передачи беззнаковых аргументов в конструктор // Вариант 1 (используем static_assert) ////////////////////////////////////////////////////////////////////
template class SomeClass { public: template SomeClass(const Args& ...args) { UnPack(args... ); } private: template void UnPack(const First& F, const Last&... L) { UnPack(F); UnPack(L...); } template void UnPack(const First& Value) { static_assert(std::is_same::value,"Type mismatch!"); std::cout << Value << ":"; } };
int main() {
// норм - передаётся нужный тип std::size_t i=1,j=2,k=3; SomeClass S1(i,j,k);
// норм - передаются беззнаковые константы SomeClass S2(1u,2u,3u);
// фэйл - знаковые типы не проходят // int a=1,b=2,c=3; // SomeClass S3(a,b,c);
return 0; }
Вариант 2 (std::enable_if):
#include #include #include
//////////////////////////////////////////////////////////////////// // Пример проверки передачи беззнаковых аргументов в конструктор // Вариант 2 (используем std::enable_if) ////////////////////////////////////////////////////////////////////
template class SomeClass { public: template SomeClass(const Args& ...args) { UnPack(args... ); } private: template void UnPack(const First& F, const Last&... L) { UnPack(F); UnPack(L...); } template void UnPack(const First& Value, typename std::enable_if::value>::type* = 0) { std::cout << Value << ":"; } };
int main() {
// норм - передаётся нужный тип std::size_t i=1,j=2,k=3; SomeClass S1(i,j,k);
// норм - передаются беззнаковые константы SomeClass S2(1u,2u,3u);
// фэйл - знаковые типы не проходят // int a=1,b=2,c=3; // SomeClass S3(a,b,c);
return 0; }
В принципе, вопрос решен. Однако, если будут более изящные варианты - вэлкомъ! :)

Комментариев нет:

Отправить комментарий