Можно ли использовать параметр шаблона по умолчанию перед нестандартными?

Следующий фрагмент кода компилируется на gcc-4.7.1:

struct X {};

template <class T = X, typename U>
void f(const U& m) {
}


int main() {
    f<>(0);
}

Однако этого не происходит:

struct X {};

template <class T = X, typename U>
void f(const U& m) {
    auto g = [] () {};
}


int main() {
    f<>(0);
}

gcc-4.7.1 жалуется:

c.cpp: In function 'void f(const U&)':
c.cpp:5:15: error: no default argument for 'U'

Итак, мой вопрос: ставит ли параметры по умолчанию параметры, отличные от параметров по умолчанию, в шаблоне функции? Если да, то почему вторая не компилируется? Если нет, то почему первый компилируется? Как стандарт С++ 11 говорит об этом синтаксисе?

Ответ 1

Это явно запрещено для классов и псевдонимов. n3290 § 14.1.11 гласит:

Если шаблонный шаблон шаблона класса или шаблон псевдонима имеет шаблон-аргумент по умолчанию, каждый последующий template-parameter должен либо иметь заданный по умолчанию шаблон-аргумент, либо быть параметром шаблона пакет

Для функций единственное ограничение, по-видимому, связано с пакетами параметров:

Пакет параметров шаблона функции не должен быть за которым следует другой параметр шаблона, если этот параметр шаблона не может быть выведен или имеет значение по умолчанию Аргумент

Но ясно, что это не касается этого случая.

Учитывая, что ничто в § 14 запрещает его для функций, кажется, мы должны предположить, что это разрешено.

A примечание из отчетов рабочей группы, похоже, подтверждает, что это намерение. Первоначальная предлагаемая формулировка этого раздела:

Если шаблонный шаблон шаблона шаблона имеет шаблон-аргумент по умолчанию, все последующие параметры шаблона должны иметь заданный аргумент шаблона по умолчанию. [Примечание: Это не является обязательным требованием для шаблонов функций, поскольку аргументы шаблона могут быть выведены (14.8.2 [temp.deduct]).]

Я не вижу, где эта заметка прошла в финальной версии.