Страницы

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

воскресенье, 22 декабря 2019 г.

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

#cpp11 #cpp14 #cpp17


Пусть есть такая конструкция:

template
class SomeClass {
  template
  SomeClass(Args& ...args) {}
};


Каким образом можно "уговорить" компилятор принимать в пакет только одинаковые типы,
и как указать конкретный тип (пусть, например, double)?
    


Ответы

Ответ 1



Вопрос решен Помогло чтение "Язык программирования С++. Лекции и упражнения. 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; } В принципе, вопрос решен. Однако, если будут более изящные варианты - вэлкомъ! :)

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

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