Как P0522R0 разбивает код?

Сегодня я читал страницу поддержки С++ 17 для clang. Я заметил что-то странное. Параметр "Параметры шаблона шаблона сопоставления для совместимых аргументов" (P0522R0) отмечен как частичный, потому что он должен быть активирован с помощью переключателя. Их примечание говорит:

Несмотря на то, что это разрешение отчета об ошибке, эта функция отключена по умолчанию во всех языковых версиях и может быть включена явно с помощью флагов -frelaxed-template-template-args в Clang 4. Изменения в стандарте отсутствуют соответствующее изменение для частичного упорядочения шаблонов, что приводит к ошибкам неоднозначности для разумного и ранее действующего кода. Ожидается, что этот вопрос будет исправлен в ближайшее время.

Какие конструкторы ломаются, когда эта функция активирована? Почему он может сломать код и как?

Ответ 1

У вас может быть такой код:

template<template<typename> typename>
struct Foo {};

template<typename, typename = void>
struct Bar {};

Foo<Bar> unused;

Без разрешения дефекта unused будет плохо сформирован, потому что foo принимает шаблон только с одним параметром шаблона, а не с двумя. Если вы полагаетесь на это (возможно, для SFINAE):

template<template<typename> typename>
void foo();

template<template<typename, typename> typename>
void foo();

template<typename, typename = void>
struct Bar {};

int main() {
    foo<Bar>(); // ambiguous after resolution!
}

Тогда вызов не получится! Проблема в том, что не было соответствующего изменения частичного упорядочения, и поэтому обе функции-кандидаты имеют одинаковую жизнеспособность, а вызов неоднозначен.

Ответ 2

Более распространенный сценарий - это когда некоторый код хочет проверить аргументы шаблона с помощью набора частичных специализаций, например:

template<class> struct Foo;

template<template<class> class X, class T> 
struct Foo<X<T>> { /* ... */ };

template<template<class, class> class X, class T, class U> 
struct Foo<X<T, U>> { /* ... */ };

// etc., etc.

Foo<std::vector<int>> теперь плохо сформирован без соответствующего исправления частичного упорядочения.