mar*_*inj 3 c++ templates decltype language-lawyer
我想用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();
}
Run Code Online (Sandbox Code Playgroud)
所以(不确定编译器版本):
clang - 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();
Run Code Online (Sandbox Code Playgroud)
Visual Studio 2013 - 更新4
fatal error C1001: An internal error has occurred in the compiler.
Run Code Online (Sandbox Code Playgroud)
非类型模板参数不能具有函数类型.它们可以有指向函数类型的指针,标准中有一个段落暗示你的代码是正确的 - [temp.param]/8:
将"数组
T"或"函数返回T" 类型的非类型模板参数分别调整为"指向指针T"或"指向函数返回的指针" 类型T.
但是,目前尚不清楚这是在模板参数替换之后还是之前完成,这在此缺陷报告中有所涉及.一个简单的解决方法是简单地写
using df = decltype(&f);
Run Code Online (Sandbox Code Playgroud)
演示.
using df = decltype((f));工作?[dcl.type.simple]/4:
对于表达式
e,表示的类型decltype(e)定义如下:
- if
e是未加密码的id-expression或未加括号的类成员访问(5.2.5),decltype(e)是名为的实体的类型e.如果没有这样的实体,或者如果e命名了一组重载函数,那么该程序就会形成错误;- 否则,如果
e是xvalue,decltype(e)则是T&&,其中T的类型是e;- 否则,如果
e是左值,decltype(e)则是T&,其中T的类型e;- 否则,
decltype(e)是的类型e.
(f)括号和左值,因此decltype((f))是对f函数类型的左值引用void(&)(int).模板参数可以引用函数类型,因此它可以工作.但是,由于这个事实非常违反直觉(而且不是很清楚),decltype(&f)因此在代码中应该减少刺激性.
| 归档时间: |
|
| 查看次数: |
212 次 |
| 最近记录: |