Как P0522R0 нарушает код?

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

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

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

2 ответа

Решение

Вы можете иметь такой код:

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!
}

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

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

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>> теперь плохо сформирован без соответствующего исправления частичного упорядочения.

Другие вопросы по тегам