Какой подход лучше для предоставления констант времени компиляции функции? Аргумент функции и параметр шаблона

У меня есть функция ведения журнала, вызываемая в нескольких местах по всему коду. Для каждого журнала я должен указать 2 константы времени компиляции. Есть 2 подхода к выполнению:

(1) Аргумент функции:

template<typename T>
void log (const T &obj, const int LINE, const int COUNT)
{
  // T is used for some purpose
  if(debug)
    logging(obj.out(), LINE, COUNT);
}

назовите это как,

log(str, __LINE__, __COUNTER__);

(2) Параметр шаблона:

template<typename T, int LINE, int COUNT>
void log (T &obj)
{
  // T is used for some purpose
  if(debug)
    logging(obj.out(), LINE, COUNT);
}

назовите это как,

log<__LINE__, __COUNTER__>(str);

Я не могу решить, потому что 1-й подход предлагает простоту, но мы передаем константу во время компиляции. Второй подход идеален, но время компиляции, вероятно, увеличится. Эта задача утомительна, и я еще не реализовал ни одну из них, поэтому у меня нет эталона.

Будет большим подспорьем, если кто-то сможет ответить на этот вопрос из своего опыта/знаний.


person iammilind    schedule 19.12.2011    source источник
comment
Как лучше определить? Они оба работают, так по каким критериям вы бы сказали, что один лучше другого?   -  person Nicol Bolas    schedule 19.12.2011
comment
@NicolBolas, так как я хочу выбрать лучший из двух в зависимости от времени компиляции и времени выполнения. Также есть небольшая модификация в коде примера.   -  person iammilind    schedule 19.12.2011
comment
Что бы ни делала эта функция logging, она наверняка будет работать медленнее, чем передача двух целых чисел в качестве аргументов. Поэтому я не вижу, как производительность во время выполнения сильно изменится в любом случае. Это подозрительно похоже на преждевременную оптимизацию.   -  person Nicol Bolas    schedule 19.12.2011
comment
@Nichol: это наверняка будет медленнее, чем передача двух целых чисел в качестве аргументов - я не думаю, что это вообще точно в случае, когда debug ложно. Конечно, она может быть незначительной.   -  person Steve Jessop    schedule 19.12.2011


Ответы (2)


Я бы пошел с первым вариантом. Влияние передачи двух целых чисел на производительность незначительно. Оптимизатор также, вероятно, встроит вызов функции, и в этом случае между ними не будет никакой разницы. Второй вариант я считаю плохой идеей, так как вы будете создавать много версий одной и той же функции без всякой причины.

person ronag    schedule 19.12.2011
comment
Хорошо, есть небольшое изменение в синтаксисе вопроса. Сама log является функцией template, я думал не упоминать об этом... но обнаружил, что это будет полезно. Кроме того, не будет ли компилятор также оптимизировать несколько версий template log? - person iammilind; 19.12.2011
comment
Ну, будет только несколько версий первой функции журнала, std::string, std::wstring, char*, wchar_t*. В то время как в основном каждый вызов функции второй версии приведет к новой функции. Оптимизатор, вероятно, справится с этим, но вы получите тот же результат с более длительным временем компиляции. - person ronag; 19.12.2011

Поскольку выбор между этими двумя вариантами влияет на вызывающий код, я бы рекомендовал вести журнал с помощью макроса. Тогда вам не нужно беспокоиться о том, какой из них лучше, потому что между ними легко переключаться.

После того, как вы написали свое реальное приложение, вы можете возиться с определением макроса, чтобы сравнить их. Или нет, если есть более продуктивные области для оптимизации. Если окажется, что это имеет большое значение, вы даже можете оставить его открытым для конфигурации сборки, чтобы решить, использовать ли -DLOGGING_COMPILES_QUICKLY или -DLOGGING_RUNS_QUICKLY.

Еще одно потенциальное преимущество макроса: вы можете сделать так, чтобы первый аргумент оценивался тогда и только тогда, когда debug истинно. Я не знаю, что такое интерфейс str или откуда берутся эти объекты, но если создание правильного значения для передачи в log стоит чего-то, а затем log не использует его в случае отсутствия отладки, тогда это потенциальная трата времени выполнения.

person Steve Jessop    schedule 19.12.2011
comment
Хороший ответ... В большинстве случаев LINE & COUNT не используется. Какая альтернатива лучше в этом случае для производственного кода? - person iammilind; 19.12.2011
comment
@iammilind: Если debug является константой времени компиляции, а вызов log встроен, то сгенерированный код, вероятно, должен быть одинаковым в любом случае, хотя это проблема QOI. Если вы хотите узнать подробности для конкретной реализации, проверьте дизассемблирование. - person Steve Jessop; 19.12.2011