Компилятор вынужден оценивать выражения в зависимости от параметров шаблона? - PullRequest
1 голос
/ 16 июня 2020

Рассмотрим этот фрагмент кода:

#include <iostream>

struct A {

    void f() { std::cout << "f"; }
    void g() { std::cout << "g"; }

    template <bool b>
    void call() { (b ? f() : g()); }
};

int main()
{
    A().call<true>();
}

В зависимости от параметра template, переданного в call, будет вызываться либо f, либо g. Мой вопрос: если компилятор каким-то образом вынужден предварительно оценить условие if. Рассмотрим другую возможную реализацию call:

template <bool b>
void call() { 
    bool x = b;    
    (x ? f() : g()); 
}

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

Действительно, если я протестирую это поведение с помощью godbolt , похоже, именно это и произойдет.

Есть ли какая-то часть стандарта, которая определяет, какие выражения шаблона имеют для оценки во время компиляции?

(Конечно, в этом простом примере я мог бы легко напишите специализации для b == true и b == false, но вопрос не об этом.)

1 Ответ

2 голосов
/ 16 июня 2020

Все выражения шаблона оцениваются во время компиляции, потому что шаблоны не существуют во время выполнения. Вы можете использовать if constexpr, который гарантированно оценивается во время компиляции:

template <bool b>
void call() { if constexpr (b) f(); else g(); }

В вашем примере (для b = true) это будет

void call() { f(); }

независимо от уровня оптимизации .

Однако при использовании обычного if или тернарного оператора сгенерированный код можно легко оптимизировать. В вашем примере (снова для b=true) экземпляр шаблона создает что-то вроде этого:

void call() { (true ? f() : g()); }

, которое компилятор может легко оптимизировать, если вы ему позволите. G ++ с -O3, например, просто удаляет экземпляр A и вызов call полностью и просто перемещает std::cout << "f" в main. См. godbolt .


Заключение: все выражения шаблона оцениваются во время компиляции, но компилятор может распознать, является ли выражение или переменная константой, и может оптимизировать такие случаи, но компилятор не обязан это делать (вам не нужен оптимизированный код, когда вы пытаетесь что-то отладить)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...