使用函数的 decltype 生成的非类型模板参数
nontype template parameter produced with decltype for function
我想用 decltype 代替编写函数签名,发现它不能与大多数编译器一起编译。它是新功能还是未指定的行为?
#include <iostream>
template <typename T, T nontype>
struct CL {
void call() { nontype(123); }
};
void f(int n) {
std::cout << n << std::endl;
}
CL<void(*)(int), f> cl7;
using df = decltype(f);
CL<df, f> cl8; // << error
int main() {
cl8.call();
}
所以(不太确定编译器版本):
铿锵声 - 3.4
http://rextester.com/UOIV91915
编译、运行、生成输出
g++ 4.9+
http://coliru.stacked-crooked.com/a/dbec1e202c48fd81
main.cpp:14:9: error: 'void(int)' is not a valid type for a template non-type parameter
CL<df, f> cl8; // << error
^
main.cpp:14:14: error: invalid type in declaration before ';' token
CL<df, f> cl8; // << error
^
main.cpp: In function 'int main()':
main.cpp:17:6: error: request for member 'call' in 'cl8', which is of non-class type 'int'
cl8.call();
Visual Studio 2013 - 更新 4
fatal error C1001: An internal error has occurred in the compiler.
非类型模板参数不能有函数类型。它们可以有指向函数类型的指针,并且标准中有一段以某种方式暗示您的代码是正确的 - [temp.param]/8:
A non-type template-parameter of type “array of T
” or “function
returning T
” is adjusted to be of type “pointer to T
” or “pointer to
function returning T
”, respectively.
但是,尚不清楚这是在模板参数替换之后还是之前完成的,后者已涵盖 in this defect report。一个简单的解决方法是简单地写
using df = decltype(&f);
Demo.
为什么 using df = decltype((f));
有效?
[dcl.type.simple]/4:
For an expression e
, the type denoted by decltype(e)
is defined as
follows:
- if
e
is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e)
is the type of the entity
named by e
. If there is no such entity, or if e names a set of
overloaded functions, the program is ill-formed;
- otherwise, if
e
is an xvalue, decltype(e)
is T&&
, where T
is the type of e
;
- otherwise, if
e
is an lvalue, decltype(e)
is T&
, where T
is the type of e
;
- otherwise,
decltype(e)
is the type of e
.
(f)
是带括号的左值,因此 decltype((f))
是对 f
的函数类型 - void(&)(int)
的左值引用。模板参数可以引用函数类型,因此它可以工作。然而,由于这个事实非常违反直觉(而且不太为人所知),decltype(&f)
在您的代码中应该不那么令人恼火。
我想用 decltype 代替编写函数签名,发现它不能与大多数编译器一起编译。它是新功能还是未指定的行为?
#include <iostream>
template <typename T, T nontype>
struct CL {
void call() { nontype(123); }
};
void f(int n) {
std::cout << n << std::endl;
}
CL<void(*)(int), f> cl7;
using df = decltype(f);
CL<df, f> cl8; // << error
int main() {
cl8.call();
}
所以(不太确定编译器版本):
铿锵声 - 3.4 http://rextester.com/UOIV91915
编译、运行、生成输出
g++ 4.9+ http://coliru.stacked-crooked.com/a/dbec1e202c48fd81
main.cpp:14:9: error: 'void(int)' is not a valid type for a template non-type parameter
CL<df, f> cl8; // << error
^
main.cpp:14:14: error: invalid type in declaration before ';' token
CL<df, f> cl8; // << error
^
main.cpp: In function 'int main()':
main.cpp:17:6: error: request for member 'call' in 'cl8', which is of non-class type 'int'
cl8.call();
Visual Studio 2013 - 更新 4
fatal error C1001: An internal error has occurred in the compiler.
非类型模板参数不能有函数类型。它们可以有指向函数类型的指针,并且标准中有一段以某种方式暗示您的代码是正确的 - [temp.param]/8:
A non-type template-parameter of type “array of
T
” or “function returningT
” is adjusted to be of type “pointer toT
” or “pointer to function returningT
”, respectively.
但是,尚不清楚这是在模板参数替换之后还是之前完成的,后者已涵盖 in this defect report。一个简单的解决方法是简单地写
using df = decltype(&f);
Demo.
为什么 using df = decltype((f));
有效?
[dcl.type.simple]/4:
For an expression
e
, the type denoted bydecltype(e)
is defined as follows:
- if
e
is an unparenthesized id-expression or an unparenthesized class member access (5.2.5),decltype(e)
is the type of the entity named bye
. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;- otherwise, if
e
is an xvalue,decltype(e)
isT&&
, whereT
is the type ofe
;- otherwise, if
e
is an lvalue,decltype(e)
isT&
, whereT
is the type ofe
;- otherwise,
decltype(e)
is the type ofe
.
(f)
是带括号的左值,因此 decltype((f))
是对 f
的函数类型 - void(&)(int)
的左值引用。模板参数可以引用函数类型,因此它可以工作。然而,由于这个事实非常违反直觉(而且不太为人所知),decltype(&f)
在您的代码中应该不那么令人恼火。