Если вы хотите поддерживать как можно больше типов контейнеров, вам следует использовать наименее ограничивающее определение:
template <typename FirstContainer, typename SecondContainer>
void doStuff(FirstContainer& first, SecondContainer& second)
{
}
Это связано с тем, что типы контейнеров бывают разных вкусов, например, std::array
- это шаблон, принимающий тип значения и статический размер в качестве аргумента, std::vector
- это шаблон, принимающий тип значения и распределитель, некоторые пользовательские StringList
могут вообще не быть шаблоном.
Ваша реализация может иметь определенные требования к поддерживаемым контейнерам, например, он может работать только для контейнеров целочисленных типов. Но чаще всего это просто неявный результат реализации. Возьмем для примера простую функцию суммирования значений двух контейнеров:
template <typename FirstContainer, typename SecondContainer>
int sum(const FirstContainer& first, const SecondContainer& second)
{
int result = 0;
for (auto value : first)
result += value;
for (auto value : second)
result += value;
return result;
}
Эта функция отлично работает с любыми типами значений, которые могут быть добавлены к целому числу. Если его нельзя добавить (например, std::string
), это в конечном итоге приведет к ошибке компиляции.
(Обратите внимание, что эту функцию можно написать еще более обобщенно с автоматически выводимым типом суммы вместо int
)
Если вам не хватает этих «неявных требований», вы можете добавить явные проверки, используя static_assert
:
template <typename FirstContainer, typename SecondContainer>
int sum(const FirstContainer& first, const SecondContainer& second)
{
int result = 0;
for (auto value : first)
{
static_assert(std::is_same_v<int, decltype(value)>, "FirstContainer does not hold integers");
result += value;
}
for (auto value : second)
{
static_assert(std::is_same_v<int, decltype(value)>, "SecondContainer does not hold integers");
result += value;
}
return result;
}
Теперь ваша функция принимает только контейнеры, содержащие простой int
, ничего больше.
Вы также можете использовать std::enable_if
, чтобы полностью «отключить» вашу функцию для неподдерживаемых контейнеров:
template <typename FirstContainer, typename SecondContainer>
auto sum(const FirstContainer& first, const SecondContainer& second)
-> std::enable_if_t<
std::is_same_v<typename FirstContainer::value_type, int> &&
std::is_same_v<typename SecondContainer::value_type, int>,
int
>
{
int result = 0;
for (auto value : first)
result += value;
for (auto value : second)
result += value;
return result;
}
Теперь ваша функция ограничена контейнерами с вложенным typedef value_type
для типа int
.