Использование параметров шаблона по умолчанию в вариативных параметрах шаблона шаблона

Я обнаружил, что приведенный ниже минимальный пример работает с gcc, clang и даже с Visual Studio, но не компилируется с icc. Я пытаюсь определить, является ли это действительным С++, но я не могу найти соответствующие части стандарта, которые отвечают на мой вопрос, поскольку это несколько разных концепций.

// struct with multiple template parameters
template<typename A, typename B = int>
struct C
{

};

// struct that tries to use C's default second parameter without specifying it
template<typename D, template<typename E, typename ...> class F>
struct G
{
  F<D> h;
};

int main()
{
  G<char, C> i;
}

С icc (16.0.3) компиляция выдает следующую ошибку:

struct.cpp(12): error: too few arguments for template template parameter "F"
    F<D> h;

          detected during instantiation of class "G<D, F> [with D=char, F=C]" at line 17

Это действительный С++?

Мне кажется, что так и должно быть, потому что C имеет значение по умолчанию для второго параметра шаблона, а это означает, что F<D> с F = C должны быть допустимой конструкцией.


person ryan    schedule 06.06.2016    source источник
comment
Вы пробовали `template‹typename ...› class F`?   -  person Yakk - Adam Nevraumont    schedule 06.06.2016
comment
@Yakk: к сожалению, это не решает проблему.   -  person ryan    schedule 08.06.2016
comment
Может кто-нибудь объяснить мне, почему это вообще работает, когда G‹char, C› не указывает даже первый аргумент шаблона для C? Я ожидал чего-то вроде G‹char, C‹SomeType››.   -  person user2962533    schedule 14.06.2016
comment
Второй аргумент для G — это параметр шаблона шаблона, поэтому мы передаем класс шаблона без параметров шаблона. Я надеюсь, что это полезно, если нет, возможно, этот пост объясняет это лучше, чем я здесь: codingcastles.blogspot.com/2009/04/   -  person ryan    schedule 15.06.2016
comment
Название этого вопроса заставило меня усмехнуться. Это как топливо для людей, говорящих, что C++ слишком сложен.   -  person user2962533    schedule 23.06.2016


Ответы (1)


Я считаю, что это ошибка gcc/clang. Это связано с [все еще открытым] CWG Issue 150. . Представленное обоснование включает в себя:

Аргументы по умолчанию разрешены для параметров параметра шаблона шаблона, и только эти аргументы по умолчанию будут рассматриваться в специализации параметра шаблона шаблона в определении шаблона; любые аргументы по умолчанию для параметров аргумента шаблона шаблона игнорируются.

Параметр шаблона шаблона F не имеет аргументов по умолчанию, а аргументы по умолчанию для C игнорируются. Таким образом, мы должны получить плохо сформированную специализацию, как предполагает ICC.

В примерах, представленных в выпуске, и gcc, и clang, по-видимому, реализуют правило (ни один из них не разрешает вызов f(), и оба проходят путь operator float() в примере Марка Митчелла.

person Barry    schedule 06.06.2016
comment
Спасибо за ссылку на CWG-150. Важным отличием здесь является то, что у нас есть вариативные параметры шаблона, поэтому в этой ситуации можно иметь вариативный список параметров шаблона нулевой длины, взяв параметр шаблона по умолчанию B = int. Это то, что делают gcc и clang, но не icc. Но проблема, упомянутая в CWG-150, применима только в том случае, если мы удалим список параметров вариативного шаблона и заменим его просто typename вместо typename.... - person ryan; 06.06.2016
comment
@ryan Ну, эта проблема намного старше C ++ 11, поэтому она не будет относиться к шаблонам с переменным числом аргументов. Но в конечном итоге это одна и та же концепция. - person Barry; 06.06.2016
comment
Грустно: можете ли вы придумать оправдание, почему они не могли сначала применить аргументы шаблона шаблона по умолчанию, а затем аргументы исходного шаблона по умолчанию? - person Yakk - Adam Nevraumont; 08.06.2016
comment
@Yakk Нет, но я бы не стал придавать этому большого значения. - person Barry; 08.06.2016