Какова предпочтительная конструкция функции шаблона, требующей значения параметра по умолчанию?
-
20-09-2019 - |
Вопрос
В настоящее время я работаю над очисткой API, полного шаблонов функций, и у меня возникло сильное желание написать следующий код.
template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);
Когда я вызываю этот шаблон, я хотел бы сделать это следующим образом.
std::string text("hello");
doWork(100, 20.0, &text);
doWork('a', text); // oops!
doWork<char, std::string, void>('a', text); // to verbose!
К сожалению, второй вызов не компилируется, поскольку компилятор не может определить тип необязательного параметра.Это прискорбно, поскольку меня действительно не волнует тип параметра, а важно, чтобы его значение было NULL.Кроме того, я бы хотел избежать маршрута третьего вызова, поскольку он затрудняет читаемость.
Это заставило меня попытаться сделать аргумент шаблона V
имеют тип по умолчанию, что также не работает, поскольку вы не можете применить тип по умолчанию к аргументу шаблона функции (по крайней мере, используя VC++ 9.0).
template <typename T, typename U, typename V = void> // oops!
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);
Мой единственный оставшийся вариант — ввести перегрузку doWork
который ничего не знает об аргументе шаблона V
.
template <typename T, typename U>
void doWork(const T& arg1, const U& arg2)
{
doWork(arg1, arg2, 0);
}
template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg);
Это лучший подход к решению этой проблемы?Единственный недостаток, который я вижу, заключается в том, что я потенциально могу ввести множество тривиальных функций пересылки, если шаблон функции содержит множество параметров с подходящими значениями по умолчанию.
Решение
Я считаю, что ваша функция пересылки — вполне подходящее решение, хотя в вашем решении не придется ли явно указывать параметры шаблона?(0 — целочисленная константа, которую можно преобразовать в любое V*
типа.) Также doWord
против doWork
?
Как правило, старайтесь избегать необязательных параметров, если они не приносят очень большой отдачи.
Это мощь будет проще заставить клиентов вашей функции просто добавить , (void*)0
если уместно, добавьте много дополнительного механизма для поддержки версии шаблона как с двумя параметрами, так и с тремя параметрами.Однако это зависит от ожидаемого использования.
Другие советы
С точки зрения клиентского кода, если у него нет третьего параметра, зачем его изобретать?
Итак, если вы стремитесь к удобству использования и читабельности, я согласен с вашим методом-оберткой:это имеет смысл, и обертка ты написал отвечает за достойное значение третьего параметра ты необходимо.
Кроме того, при необходимости можно использовать разные значения по умолчанию для разных специализаций.
Одна из возможностей — изменить порядок аргументов шаблона, чтобы необязательный аргумент был первым.
template <typename V, typename T, typename U>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);
doWork<void>('a', text);
Переадресация тоже выглядит нормально.
Но похоже, что аргументы и шаблоны по умолчанию не совпадают.