首页 > 解决方案 > 使用命名空间中的模板调用模板模板方法时出现错误的 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
}

这是一个活生生的例子。

没有 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 产生错误的错误吗?

标签: c++templatesc++17clang++

解决方案


向量是

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

注意它需要2个参数。

template<class>class中,如果默认第二个参数,则带有2 个参数的模板可以匹配;在中,这是不正确的。

至于中的 clang,如果您实现此功能,他们会在标准中发现一个错误:(通过上述评论中的 @cpplearner)

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

中,这可能有效:

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

因为有规则可以class...匹配任意数量的参数。


推荐阅读