模板模板 class 中 non-type 参数的类型在 C++14 中不可推导,但在 C++17 中可推导
Type of non-type parameter in template template class is non deducible in C++14 but deducible in C++17
标题有点混乱,但我的意思是这个具体案例:
template<class>
struct get_type_of_nontype;
template<class T, T Value, template<T> class Template>
struct get_type_of_nontype<Template<Value>> {
using type = T;
};
所以我可以这样使用它:
#include <type_traits>
template<int I>
class int_non_type {};
static_assert(
std::is_same<typename get_type_of_nontype<int_non_type<0>>::type, int>::value,
"T is deduced to be `int` as `template<T> class Template` is `template<int> class int_non_type`"
);
这在 C++17 中工作正常。在 C++14 中,我得到以下错误:
海湾合作委员会 8:
<source>:5:8: error: template parameters not deducible in partial specialization:
struct get_type_of_nontype<Template<Value>> {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:8: note: 'T'
叮当声 7:
<source>:5:8: error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct get_type_of_nontype<Template<Value>> {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:4:16: note: non-deducible template parameter 'T'
template<class T, T Value, template<T> class Template>
^
然后他们都抱怨struct get_type_of_nontype<int_non_type<0>>
不完整,所以typename get_type_of_non_type<int_non_type<0>>::type
无法编译。
为什么 C++14 和 C++17 之间存在差异?这只是一个编译器错误吗?如果没有,有没有办法在 C++14 中做到这一点?
[temp.deduct.type] 第 13 和 14 段中的标准措辞已更改。所以是的,您的示例在 C++14 中无效,但由于新的语言功能,在 C++17 中是允许的。
C++14:
A template type argument cannot be deduced from the type of a non-type template-argument.
[Example:
template<class T, T i> void f(double a[10][i]);
int v[10][20];
f(v); // error: argument for template-parameter T cannot be deduced
-- end example]
C++17:
When the value of the argument corresponding to a non-type template parameter P
that is declared with a dependent type is deduced from an expression, the template parameters in the type of P
are deduced from the type of the value. [Example:
template<long n> struct A { };
template<typename T> struct C;
template<typename T, T n> struct C<A<n>> {
using Q = T;
};
using R = long;
using R = C<A<2>>::Q; // OK; T was deduced to long from the
// template argument value in the type A<2>
-- end example] The type of N
in the type T[N]
is std::size_t
. [Example:
template<typename T> struct S;
template<typename T, T n> struct S<int[n]> {
using Q = T;
};
using V = decltype(sizeof 0);
using V = S<int[42]>::Q; // OK; T was deduced to std::size_t from the type int[42]
-- end example]
[Example:
template<class T, T i> void f(int (&a)[i]);
int v[10];
void g() {
f(v); // OK: T is std::size_t
}
-- end example]
这似乎与另一个 C++17 模板更改有关:C++17 是第一个允许在非类型模板参数中使用占位符类型的版本,如 template <auto Value>
或 template <auto* Ptr>
.我希望编译器实现需要一些类似的逻辑来支持这两种语言特性。
标题有点混乱,但我的意思是这个具体案例:
template<class>
struct get_type_of_nontype;
template<class T, T Value, template<T> class Template>
struct get_type_of_nontype<Template<Value>> {
using type = T;
};
所以我可以这样使用它:
#include <type_traits>
template<int I>
class int_non_type {};
static_assert(
std::is_same<typename get_type_of_nontype<int_non_type<0>>::type, int>::value,
"T is deduced to be `int` as `template<T> class Template` is `template<int> class int_non_type`"
);
这在 C++17 中工作正常。在 C++14 中,我得到以下错误:
海湾合作委员会 8:
<source>:5:8: error: template parameters not deducible in partial specialization:
struct get_type_of_nontype<Template<Value>> {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:8: note: 'T'
叮当声 7:
<source>:5:8: error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used [-Wunusable-partial-specialization]
struct get_type_of_nontype<Template<Value>> {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:4:16: note: non-deducible template parameter 'T'
template<class T, T Value, template<T> class Template>
^
然后他们都抱怨struct get_type_of_nontype<int_non_type<0>>
不完整,所以typename get_type_of_non_type<int_non_type<0>>::type
无法编译。
为什么 C++14 和 C++17 之间存在差异?这只是一个编译器错误吗?如果没有,有没有办法在 C++14 中做到这一点?
[temp.deduct.type] 第 13 和 14 段中的标准措辞已更改。所以是的,您的示例在 C++14 中无效,但由于新的语言功能,在 C++17 中是允许的。
C++14:
A template type argument cannot be deduced from the type of a non-type template-argument.
[Example:
template<class T, T i> void f(double a[10][i]); int v[10][20]; f(v); // error: argument for template-parameter T cannot be deduced
-- end example]
C++17:
When the value of the argument corresponding to a non-type template parameter
P
that is declared with a dependent type is deduced from an expression, the template parameters in the type ofP
are deduced from the type of the value. [Example:template<long n> struct A { }; template<typename T> struct C; template<typename T, T n> struct C<A<n>> { using Q = T; }; using R = long; using R = C<A<2>>::Q; // OK; T was deduced to long from the // template argument value in the type A<2>
-- end example] The type of
N
in the typeT[N]
isstd::size_t
. [Example:template<typename T> struct S; template<typename T, T n> struct S<int[n]> { using Q = T; }; using V = decltype(sizeof 0); using V = S<int[42]>::Q; // OK; T was deduced to std::size_t from the type int[42]
-- end example]
[Example:
template<class T, T i> void f(int (&a)[i]); int v[10]; void g() { f(v); // OK: T is std::size_t }
-- end example]
这似乎与另一个 C++17 模板更改有关:C++17 是第一个允许在非类型模板参数中使用占位符类型的版本,如 template <auto Value>
或 template <auto* Ptr>
.我希望编译器实现需要一些类似的逻辑来支持这两种语言特性。