«If constexpr (что-то ложное)» ВСЕГДА опускает создание шаблона - PullRequest
3 голосов
/ 28 мая 2019

Будет ли эта функция шаблона f<X>() всегда НЕ создаваться?

if constexpr(something false){
     //some template function OR function in template class
     f<X>();
}

Ниже приведен мой тест ( coliru MCVE ).
Я создал fun<S>(), который будет создавать экземпляр E<S> тогда и только тогда, когда S!=void.
Затем я звоню fun<void>(), fun<int>() и fun<float>().

Я полагаю, if constexpr(false) заставляет компилятор C ++ пропускать часть #1 для fun<void>().
Мой countRunner должен быть ++ только 2 раза.

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

(для меня напечатано 2, но один эксперимент ничего не доказывает.)

#include<iostream>
int countRunner=0;
template<class T> class E{
    public: static int countIndex;
    public: E(){
        if(false){
            int unused=E::countIndex;
        }
    }
};
template<class T> int E<T>::countIndex=countRunner++;
template<class S> void fun(){
    if constexpr(!std::is_same_v<void,S>){
        E<S> e;  //#1  - S=int,float, but never void
    }
}
int main (){
    fun<void>();
    fun<int>();
    std::cout<<"testResult="<<countRunner<<std::endl;
    fun<float>();
}

Могу ли я полагать, что E<void> никогда не будет создан?
Пожалуйста, предоставьте некоторые (полу) официальные ссылки, чтобы я успокоился.

Редактировать: Я только что нашел http://eel.is/c++draft/stmt.if#2 и "If constexpr" в C ++ 17 не работает в не шаблонной функции .

Если оператор if имеет форму if constexpr , значение условие должно быть контекстно преобразованным константным выражением типа bool; эта форма называется оператором constexpr, если . Если значение из преобразованного условия ложно, первое подзаголовок является выброшенное заявление, в противном случае второе подзаголовок, если оно есть, выброшенное заявление. Во время воплощения вложения шаблонная сущность, если условие не зависит от значения после инстанцирование, выброшенное подстатейство (если есть) не инстанцирован . [Примечание: использование Odr в отброшенном выражении не требует сущность, которая будет определена. - конец примечания] кейс или по умолчанию метка в таком , если заявление должно быть связано с оператор переключения внутри того же оператора , если . Ярлык объявлен в подстановка constexpr, если заявление должно быть указано только выписка в том же подзаголовке.

Я все еще не уверен насчет слова "экземпляр" в правиле. Имеет ли он то же значение, что и в «создании экземпляра шаблона»?

1 Ответ

4 голосов
/ 28 мая 2019

Имеет ли он то же значение, что и в "создании экземпляра шаблона"?

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

[stmt.if] (выделено мной)

2 Если оператор if имеет форму if constexpr, значение условие должно быть контекстно преобразованным константным выражением типа bool; эта форма называется оператором constexpr. Если значение из преобразованного условия ложно, первое подзаголовок является выброшенное заявление, в противном случае второе подзаголовок, если оно есть, выброшенное заявление. Во время воплощения ограждения шаблонная сущность, если условие не зависит от значения после инстанцирование, выброшенное подстатейство (если есть) не инстанцирован .

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

В вашем случае это точно означает, что если std::is_same_v<void,S> истинно, тело «если» не будет частью экземпляра fun<void>.

...