P0522R0如何破坏代码?

时间:2017-11-14 18:48:22

标签: c++ language-lawyer clang++ c++17

今天我正在阅读clang的C ++ 17支持页面。我注意到一些奇怪的事情。功能将模板模板参数与兼容参数匹配P0522R0)被标记为部分,因为它必须通过开关激活。他们的注释says

  

尽管是缺陷报告的解决方案,但默认情况下在所有语言版本中都禁用此功能,并且可以使用Clang 4中的标志-frelaxed-template-template-args显式启用此功能。标准的更改缺少模板部分排序的相应变化,导致合理且先前有效的代码的模糊错误。预计这个问题很快就会得到纠正。

激活此功能后,哪种结构会中断?为什么它会破坏代码以及如何破解代码?

2 个答案:

答案 0 :(得分:14)

您可以使用以下代码:

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

然后电话会失败!问题是部分排序没有相应的变化,因此两个候选函数都具有相同的可行性,并且调用是不明确的。

答案 1 :(得分:6)

更常见的情况是某些代码想要使用一组部分特化来检查模板参数,例如:

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