Подтвердить что ты не робот

Не зависят ли по умолчанию шаблонные аргументы шаблонов функций для SFINAE?

С "независящим" здесь я подразумеваю "не зависящий от любых других аргументов шаблона этого шаблона конкретной функции".

Отвечая на этот вопрос, я думал, что нашел ответ, но, согласно @Johannes (в комментариях к моему ответу), я неверно истолковываю стандарт здесь, Возьмем следующий простой пример:

#include <type_traits>

template<class T>
struct X{
  template<class U = typename T::type>
  static void foo(int){}
  static void foo(...){}
};

int main(){
  X<std::enable_if<false>>::foo(0);
}

(Текущая версия.)

Есть ли какая-либо гарантия того, что выше компилируется? GCC и Clang не согласны здесь, как это видно в живой версии при переключении между ними. Интересно, однако, что GCC принимает следующее:

#include <type_traits>

template<class T>
struct X{
  template<bool = T::f()>
  static void foo(int){}
  static void foo(...){}
};

struct Y{
  static bool f(){ return true; }
};

int main(){
  X<Y>::foo(0);
}

(Текущая версия.)

Второй фрагмент будет печатать только foo(int), если T содержит статическую функцию constexpr f. Опять же, интересно, если вы полностью удалите f из Y (или перейдете, скажем, int), GCC жалуется на отсутствующий элемент, указывая, что он не позволяет SFINAE, что противоречит предыдущему наблюдение. Clang принимает все варианты и применяет SFINAE, и мне интересно, гарантировано ли это стандартом.

(FWIW, MSVC с Nov CTP, как правило, согласуется с Clang, но сбой во втором фрагменте, если функция присутствует, вероятно, потому что у них нет constexpr. Я отправил отчет об ошибке здесь.)

4b9b3361

Ответ 1

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

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

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