P0522R0 是如何破解代码的?

How is P0522R0 breaking code?

今天在看clang的C++17支持页面。我注意到一些奇怪的事情。特性将模板模板参数匹配到兼容参数 (P0522R0) is marked as partial, because it must be activate through a switch. Their note says:

Despite being the the resolution to a Defect Report, this feature is disabled by default in all language versions, and can be enabled explicitly with the flag -frelaxed-template-template-args in Clang 4. The change to the standard lacks a corresponding change for template partial ordering, resulting in ambiguity errors for reasonable and previously-valid code. This issue is expected to be rectified soon.

激活此功能时会破坏什么样的结构?为什么它可以破解代码以及如何破解?

你可以有这样的代码:

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>> 现在格式错误,没有适当的部分排序修复。