Короткое замыкание при создании экземпляра шаблона?

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

template<bool b>
struct other
{
    static const bool value = !b;
};

template<bool b>
struct test
{
    static const bool value = b || other<b>::value;
};

int main()
{
      bool value = test<true>::value;   
}

Создают ли компиляторы экземпляр other<true> в ситуациях, подобных приведенным выше, когда создание экземпляра кажется совершенно ненужным? Или только потому, что я написал синтаксис other<b>::value, компиляторы должны создавать его экземпляры, несмотря на то, что он абсолютно ничего не дает при вычислении значения test<true>::value?

Я хотел бы услышать, а) что требуется в стандарте, и б) что фактически реализовано различными компиляторами? Приветствуются соответствующие разделы Стандарта.


person Nawaz    schedule 05.01.2011    source источник
comment
Согласно C++ Templates: The Complete Guide, стр. 307, похоже, по крайней мере, в соответствии со стандартом, что нет, компилятор не будет сокращать это выражение и действительно будет оценивать обе ветви. Я точно не знаю, почему это так или каков здесь более общий принцип действия, но это может быть хотя бы частичным ответом на ваш вопрос.   -  person templatetypedef    schedule 05.01.2011
comment
Стандарт не позволяет им делать здесь короткое замыкание. Вот почему вам нужно реализовать это самостоятельно, как здесь. Причина проста: вам нужно знать тип other<b>::value и можно ли его вообще конвертировать в bool и имеет ли смысл. Для этого необходимо создать экземпляр other<b>. Что, если его тип уступит вызову перегруженного op||? Тогда инициализатор будет недействительным.   -  person Johannes Schaub - litb    schedule 05.01.2011


Ответы (1)


Согласно спецификации С++, раздел $14.7.1/4:

"Специализация шаблона класса создается неявно, если тип класса используется в контексте, требующем полностью определенного типа объекта или если полнота типа класса влияет на семантику программы; в частности, если выражение, тип которого является специализацией шаблона класса, участвует в разрешении перегрузки"

В случае, когда вы проиллюстрировали короткое замыкание, класс должен иметь полный тип, потому что вы просматриваете его внутри, чтобы найти значение статического члена. Это не позволяет компилятору сократить выражение.

Что же касается того, что на самом деле происходит на практике, я не уверен, потому что не понимаю, как компилятор может уйти от невыполнения инстанцирования. Например, предположим, что создание экземпляра other<b> выглядело так:

template <bool B> struct other {
    typedef int value;
};

Здесь ваша программа будет неправильно сформирована, потому что other<b>::value — это тип, а не значение, но компилятор не может диагностировать ошибку без фактического создания экземпляра.

person templatetypedef    schedule 05.01.2011