Я работаю над проектом С++, и я только что определил функцию, как показано ниже:
template<typename... Args>
void func(Args&&... args) {}
Затем назовите это так:
func("abc"); // char[4]?
func("de"); // char[3]?
Мой вопрос: выведет ли компилятор две независимые функции, одну для char[4]
, а другую для char[3]
? Если я вызову много func
с const char*
, как указано выше, компилятор сгенерирует много независимых функций?
Это глупо? Должен ли я избегать этого?
На самом деле, func("abc")
и func(std::string("abc"));
для меня абсолютно одно и то же.
Так должен ли я вызывать эту функцию как func(std::string("abc"));
и func(std::string("de"));
, чтобы компилятор сгенерировал только одну функцию как void func(const std::string&);
Кстати, мой проект разработан на С++ 14.
Да, функция будет сгенерирована для каждого размера строкового литерала. Если вы используете std::string
, вы рискуете динамическим размещением, так что это компромисс между временем компиляции/исполняемым пространством и стоимостью времени выполнения. Если большинство ваших строк короткие, например, менее 15 символов, вы выиграете от единого входа, и это делает компромисс еще более тонким. Лично, если вы не заметите, что это становится проблемой, я бы придерживался того, что у вас есть сейчас.
Я полагаю, это также зависит от того, что вы ожидаете от этой функции. Всегда ли это работает со строками? Работает ли он с массивоподобными объектами? И т. д. При использовании шаблонов я лично всегда следую мантре определения максимально ограниченного возможного шаблона, чтобы было более предсказуемо то, что генерирует компилятор. Шаблоны Variadic обычно используются только в крайнем случае (или в качестве «переадресатора»), поскольку при необходимости распаковать пакет параметров шаблона вниз по линии действительно неудобно.
Это зависит от многого. Если функция короткая, она, вероятно, все равно будет встроена, так что вы ничего не потеряете. В противном случае вы должны спросить себя в реальном коде, сколько жестко закодированных строк вы собираетесь использовать? Также, возможно, стоит рассмотреть интерфейс в стиле STL с использованием указателей на начальные и конечные символы или использование std::string_view
(и, возможно, std::span
).
My question is if the compiler will deduce two independent functions, one is for char[4] and the other is for char[3]?
Будет.
If I call many func with const char* as above, the compiler will generate many independent functions?
Вы не звоните func
с const char*
. Если бы вы вызвали func
только с const char*
, то был бы только один экземпляр шаблона функции.
Вы вызываете функцию с помощью const char[4]
и const char[3]
, которые вызывают отдельные экземпляры. Будет создан экземпляр для каждого уникального набора аргументов шаблона.
Is this stupid? Should I avoid this?
Зависит от варианта использования. Во многих случаях оптимизатор просто расширяет все встроенные вызовы, и экземпляры не оставляют никаких следов их теоретического существования в сгенерированной сборке.
Может быть полезно попробовать ваш код в www.godbolt.org, чтобы увидеть, что различные компиляторы будут производить с различными флагами сборки.