使用命名空间中的模板调用模板模板方法时出现错误的clang错误

时间:2018-08-07 10:07:02

标签: c++ templates c++17 clang++

我有一个模板模板方法,当使用不在命名空间中的模板调用它时,它可以正常工作。但是,当使用命名空间中的模板调用它时,会收到一个clang错误。 MSVC和gcc编译没有问题,但是仅当我将标准设置为C ++ 17时。

这是一个最小的例子

#include <vector>

template<template<typename> typename Template>
Template<int> foo() {
    return {};
}

template <typename T>
using my_vector = std::vector<T>;

int main()
{
    foo<my_vector>(); // compiles
    foo<std::vector>(); // does not compile in clang or without C++17
}

Here is a live example.

没有C ++ 17的gcc错误是:

<source>:14:5: error: no matching function for call to 'foo'

叮当错误是:

<source>:14:22: error: no matching function for call to 'foo<template<class _Tp, class _Alloc> class std::vector>()'
<source>:4:15: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Template'

C ++ 17中的哪些更改允许这样做,并且是clang产生错误的错误?

2 个答案:

答案 0 :(得分:2)

向量是

template<class T, class Allocator=std::allocator<T>>
class vector;

请注意,它需要2个参数。

中使用2个参数的模板可以与template<class>class匹配,如果第二个参数是默认的;在中不是这样。

对于中的clang,如果您实现此功能,则它们found a bug in the standard :(通过以上注释中的@cpplearner)

  

(10):尽管是缺陷报告的解决方法,但是默认情况下,所有语言版本均禁用此功能,并且可以在Clang 4及更高版本中使用标志-frelaxed-template-template-args明确启用该功能。对标准的更改缺少模板部分排序的相应更改,从而导致合理且先前有效的代码存在歧义错误。预计此问题将很快得到纠正。

中,这可能有效:

template<template<class...> class Z>
Z<int> foo() {
  return {};
}

有些规则允许class...匹配任意数量的参数。

答案 1 :(得分:1)

  

C ++ 17中的哪些更改允许这样做,并且是clang产生错误的错误?

是的,自C ++ 17起行为发生了变化,而Clang似乎不符合该标准。

请注意,std::vector有2个模板参数(第2个具有默认值),而模板模板参数Template只需要一个。他们不匹配。

自C ++ 17(CWG 150)起,template template argument允许使用默认模板参数来匹配具有较少模板参数的模板模板参数。

template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };

template<template<class> class P> class X { /* ... */ };
X<A> xa; // OK
X<B> xb; // OK in C++17 after CWG 150
         // Error earlier: not an exact match