使用命名空间中的模板调用模板模板方法时出现 False clang 错误
False clang error when calling a template template method with a template that is in a namespace
我有一个模板模板方法,当使用不在命名空间中的模板调用它时,它工作正常。但是,当使用命名空间中的模板调用它时,出现 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'
clang 错误是:
<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 产生错误是不是一个错误?
矢量是
template<class T, class Allocator=std::allocator<T>>
class vector;
注意它需要 2 个参数。
在 c++17 templates that take 2 parameters can match template<class>class
if the 2nd one is defaulted; in c++14 这不是真的。
至于 c++17, they found a bug in the standard 中的 clang,如果您实现此功能:(通过上面评论中的@cpplearner)
(10): Despite being 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 onwards. 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.
在 c++14 这可能有效:
template<template<class...> class Z>
Z<int> foo() {
return {};
}
因为有规则让 class...
匹配任意数量的参数。
What changed in C++17 to allow this, and is it a bug that clang produces an error?
是的,自 C++17 以来行为发生了变化,Clang 似乎不符合标准。
注意 std::vector
有 2 个模板参数(第二个有默认值),而模板模板参数 Template
只需要一个。他们不匹配。
自 C++17 起(CWG 150), the default template arguments are allowed for a 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
我有一个模板模板方法,当使用不在命名空间中的模板调用它时,它工作正常。但是,当使用命名空间中的模板调用它时,出现 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'
clang 错误是:
<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 产生错误是不是一个错误?
矢量是
template<class T, class Allocator=std::allocator<T>>
class vector;
注意它需要 2 个参数。
在 c++17 templates that take 2 parameters can match template<class>class
if the 2nd one is defaulted; in c++14 这不是真的。
至于 c++17, they found a bug in the standard 中的 clang,如果您实现此功能:(通过上面评论中的@cpplearner)
(10): Despite being 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 onwards. 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.
在 c++14 这可能有效:
template<template<class...> class Z>
Z<int> foo() {
return {};
}
因为有规则让 class...
匹配任意数量的参数。
What changed in C++17 to allow this, and is it a bug that clang produces an error?
是的,自 C++17 以来行为发生了变化,Clang 似乎不符合标准。
注意 std::vector
有 2 个模板参数(第二个有默认值),而模板模板参数 Template
只需要一个。他们不匹配。
自 C++17 起(CWG 150), the default template arguments are allowed for a 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