C++ VS2015中模板类型别名出现意外行为
下面的代码使用VS15社区编译并打印出“Hello”C++ VS2015中模板类型别名出现意外行为,c++,c++11,visual-studio-2015,language-lawyer,type-alias,C++,C++11,Visual Studio 2015,Language Lawyer,Type Alias,下面的代码使用VS15社区编译并打印出“Hello” #包括 #包括 模板 使用void\u模板\u别名\u t=void; 模板 使用Func=std::function; 模板 使用FuncVoid=Func; int main() { FuncVoid hello=[]{std::cout 或者它只是一个编译器错误 如@T.C.所述,与以下内容相关: […]在那里 是否有人对函数模板的处理表示担忧 如果C++规则发生改变,类模板的成员函数: 对于模板参数T,将使用一个单一参数的函数 类型为
#包括
#包括
模板
使用void\u模板\u别名\u t=void;
模板
使用Func=std::function;
模板
使用FuncVoid=Func;
int main()
{
FuncVoid hello=[]{std::cout
或者它只是一个编译器错误
如@T.C.所述,与以下内容相关:
[…]在那里
是否有人对函数模板的处理表示担忧
如果C++规则发生改变,类模板的成员函数:
对于模板参数T
,将使用一个单一参数的函数
类型为T
的函数,如果用
T=void
?
这是一个合理的投诉,但不幸的是,成员函数/成员函数模板和类型ID同样受到解决方案的影响:
由单个非依赖类型的未命名参数组成的参数列表相当于空参数列表
因此,这两个代码段的格式都不正确,因为参数的类型确实是依赖的
它是一个正确的实现吗?如果不是,它会是什么样子
没有正确的实现。如果需要具有空参数列表的函数类型,则必须独立于模板参数指定该类型
那么,为什么上面的代码按照我最初的预期进行编译和工作呢
我的最佳猜测是:VC++在确保参数类型不是依赖类型“cvvoid
”之后,但在进行“void
->空列表转换”之前,替换了void\u template\u alias\u t
”。然而,通常很难理解VC++(或任何编译器)是如何进行空列表转换的内部思考。使用X=void;foo(X);
和之间有着天壤之别。如果其他编译器接受这一点,我会感到惊讶。哦,我太确定了。标准规定“参数列表(void)
等同于空参数列表。”,但没有指定(void)是文字文本,并且没有特殊的语法生成,G++和VisualC++都编译<代码>无效FO(x)< /> >其中代码< >代码> >代码>空> <代码>,他们编译了调用<代码>()/代码>。也许我最好明确地指出,解释在哪里<代码>(空格)
指的是一个函数,其中单个参数的类型实际上是void
,然后表示一个没有参数的函数,不适用于使用参数调用函数的模板代码,也就是说,这是不切实际的。然而MSVC和MinGW g++都接受非模板foo(My_void)
并调用foo()
:(@cheerrandhth.-Alf之后,规则是“由一个非依赖类型的未命名参数组成的参数列表void
相当于一个空参数列表”。@T.C.:因此,这在C++14中发生了变化。DR表明C++11和更早版本的自然读取,如(void)
是文本(不允许使用typedef
),是这些版本的正确选项。谢谢!
#include <functional>
#include <iostream>
template<typename T>
using void_template_alias_t = void;
template<typename T>
using Func = std::function<void( T )>;
template<typename T>
using FuncVoid = Func<void_template_alias_t<T>>;
int main()
{
FuncVoid<void> hello = [] { std::cout << "Hello\n"; };
hello();
}
#include <functional>
#include <iostream>
template<typename T>
using Func = std::function<void( T )>;
int main()
{
Func<void> hello = [] { std::cout << "Hello\n"; };
hello();
}