P0522R0如何破坏代码?

Gui*_*cot 16 c++ language-lawyer clang++ c++17

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

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

激活此功能后会出现什么样的构造?为什么它会破坏代码?

Rak*_*111 14

您可以使用以下代码:

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

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

Foo<Bar> unused;
Run Code Online (Sandbox Code Playgroud)

如果没有缺陷解决方案,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!
}
Run Code Online (Sandbox Code Playgroud)

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

  • @Guillaume是的,因为它是一个更好的匹配.但标准没有为此部分排序的文本:( (6认同)
  • 我已经看到了几个关于这个的问题,甚至自己也遇到过.我认为最常见的情况是有人正在包装一个容器,特别是`std :: vector`,而且他们忘记了它也有一个分配器,所以你最终会得到像[this]这样的代码(https:// wandbox.组织/ permlink/lYy8DNiF61ZH4Fmp) (3认同)

T.C*_*.C. 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.
Run Code Online (Sandbox Code Playgroud)

Foo<std::vector<int>> 如果没有适当的部分订购修复,现在形成不良.