Сообщение Re[5]: Помогите с вариадиками от 09.01.2018 18:14
Изменено 10.01.2018 13:11 watchmaker
Re[5]: Помогите с вариадиками
Здравствуйте, SaZ, Вы писали:
SaZ> А можете пояснить про typename T = void и почему это помогло?
Это не самая важная часть: можно и без этого.
Указания параметра по умолчанию =void используется просто чтобы задать условие окончания через специализацию (а она для функций возможна только полная).
Чаще, конечно, окончание рекурсии делается через подсчёт параметров и ту же перегрузку. Но тут у тебя все функции имеют ровно один и тот же список аргументов (const Table& table), и для них этот способ закрыт.
Хотя можно это обойти, если ввести в сигнатуру функции эти типы, добавив, например, фиктивный аргумент.
Тогда у всех функций будут разные сигнатуры и перегрузка будет работать:
Тут просто передаётся нулевой указатель (оптимизатор его выбросит потом) на кортеж, параметры которого и являются тем списком классов, который осталось проверить.
Upd: Этот код — просто демонстрация, я не говорю, что так нужно писать :)
SaZ> А можете пояснить про typename T = void и почему это помогло?
Это не самая важная часть: можно и без этого.
Указания параметра по умолчанию =void используется просто чтобы задать условие окончания через специализацию (а она для функций возможна только полная).
Чаще, конечно, окончание рекурсии делается через подсчёт параметров и ту же перегрузку. Но тут у тебя все функции имеют ровно один и тот же список аргументов (const Table& table), и для них этот способ закрыт.
Хотя можно это обойти, если ввести в сигнатуру функции эти типы, добавив, например, фиктивный аргумент.
Тогда у всех функций будут разные сигнатуры и перегрузка будет работать:
bool ValidateTuple(const Table& table, std::tuple<>*) {
return false;
}
template <typename Head, typename ...Tail>
bool ValidateTuple(const Table& table, std::tuple<Head*, Tail*...>*)
{
if (Validate_1<Head>(table))
return true;
return ValidateTuple(table, static_cast<std::tuple<Tail*...>*>(nullptr));
}
template <typename ...Tables>
bool Validate(const Table& table) {
return ValidateTuple(table, static_cast<std::tuple<Tables*...>*>(nullptr));
}
Тут просто передаётся нулевой указатель (оптимизатор его выбросит потом) на кортеж, параметры которого и являются тем списком классов, который осталось проверить.
Upd: Этот код — просто демонстрация, я не говорю, что так нужно писать :)
Re[5]: Помогите с вариадиками
Здравствуйте, SaZ, Вы писали:
SaZ> А можете пояснить про typename T = void и почему это помогло?
Это не самая важная часть: можно и без этого.
Указания параметра по умолчанию =void используется просто чтобы задать условие окончания через специализацию (а она для функций возможна только полная).
Чаще, конечно, окончание рекурсии делается через подсчёт параметров и ту же перегрузку. Но тут у тебя все функции имеют ровно один и тот же список аргументов (const Table& table), и для них этот способ закрыт.
Хотя можно это обойти, если ввести в сигнатуру функции эти типы, добавив, например, фиктивный аргумент.
Тогда у всех функций будут разные сигнатуры и перегрузка будет работать:
Тут просто передаётся нулевой указатель (оптимизатор его выбросит потом) на кортеж, параметры которого и являются тем списком классов, который осталось проверить.
Upd: Этот код — просто демонстрация, я не говорю, что так нужно писать :)
SaZ> А можете пояснить про typename T = void и почему это помогло?
Это не самая важная часть: можно и без этого.
Указания параметра по умолчанию =void используется просто чтобы задать условие окончания через специализацию (а она для функций возможна только полная).
Чаще, конечно, окончание рекурсии делается через подсчёт параметров и ту же перегрузку. Но тут у тебя все функции имеют ровно один и тот же список аргументов (const Table& table), и для них этот способ закрыт.
Хотя можно это обойти, если ввести в сигнатуру функции эти типы, добавив, например, фиктивный аргумент.
Тогда у всех функций будут разные сигнатуры и перегрузка будет работать:
template <typename... Types>
using TupleTypeList = std::tuple<Types*...>*; // сделаем список на основе существующего std::tuple, чтобы не писать для примера свой класс
bool ValidateTuple(const Table& table, TupleTypeList<>) { // перегрузка для пустого списка типов
return false;
}
template <typename Head, typename ...Tail>
bool ValidateTuple(const Table& table, TupleTypeList<Head, Tail...>) // разбор общего случая с непустым списком типов
{
if (Validate_1<Head>(table))
return true;
return ValidateTuple(table, TupleTypeList<Tail...>{});
}
template <typename ...Tables>
bool Validate(const Table& table) {
return ValidateTuple(table, TupleTypeList<Tables...>{});
}
Тут просто передаётся нулевой указатель (оптимизатор его выбросит потом) на кортеж, параметры которого и являются тем списком классов, который осталось проверить.
Upd: Этот код — просто демонстрация, я не говорю, что так нужно писать :)