2016-10-19 3 views
5

Рассмотрим следующий класс:Оператор noexcept и enable_if_t: они работают вместе?

struct S { 
    template<typename T> 
    std::enable_if_t<std::is_void<T>::value> 
    f() noexcept {} 

    template<typename T> 
    std::enable_if_t<not std::is_void<T>::value> 
    g() noexcept {} 
}; 

Как и следовало ожидать, это компилирует:

s.f<void>(); 

Это один не вместо:

s.g<void>(); 

озадачивает меня в том, что следующий main компилируется GCC (6.2) и не компилируется с помощью clang (3.9):

int main() { 
    static_assert(noexcept(&S::f<void>), "!"); 
    static_assert(noexcept(&S::g<void>), "!"); 
} 

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

Какой именно?

+1

Я думаю, что GCC решил сделать ярлык, как только выяснилось, 'g' является шаблоном функции-члена и поэтому' noexcept' может быть только 'true'. –

+0

@ T.C. Это может быть, но в этом случае специализация недействительна. Должен ли он не сбой для 'S :: g ' (скажем так) _cannot exist_ на самом деле? – skypjack

+2

Я не сказал, что GCC прав. –

ответ

3

[except.spec]/13:

Множество потенциальных исключений из выражения e пуст, если e является постоянным выражением ядра (5.20).

То есть, GCC, даже не разрешить шаблонный идентификатор, потому что он знает, с самого начала идти, что результат trueg<void> не статический член данных специализация шаблона, тип которого имеет перегруженный operator&). Будучи умным, поведение является несоответствующим, поскольку любое появление шаблона влечет за собой замену аргументов в объявление шаблона функции.

+0

Но это только ошибка, если мы создаем экземпляр 'g', и мы не создаем экземпляр' g', если нам не требуется определение, и это не влечет за собой перегрузочное разрешение, верно? – Barry

+0

@Barry "Instantiation" посвящен определению шаблона функции. Поэтому шаблон функции не создается, если не требуется его определение. Подпись создается во многих сценариях. В противном случае что-то вроде 'decltype (g ())' не будет смотреть на тип возврата 'g', который был бы действительно странным. – Columbo

+0

Но в этом случае будет задействовано разрешение перегрузки, которое вызывает создание экземпляра. – Barry

Смежные вопросы