VS2015中模板类型别名的意外行为

DaB*_*ain 12 c++ language-lawyer c++11 type-alias visual-studio-2015

以下代码与VS15社区一起编译并打印出"Hello".

#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();
}
Run Code Online (Sandbox Code Playgroud)

我认为这是不允许编译的.

我在玩,代码有点复杂.我天真地期望这个工作,但突然意识到这个代码不应该编译因为你不能做一个Func<void>(或者我错了吗?).

  • 我找到了一个神奇的解决方法吗?
  • 这是C++ 14标准的新行为吗?
  • 或者它只是一个编译器错误?

编辑:以下更简化的版本无法编译.

#include <functional>
#include <iostream>

template<typename T>
using Func = std::function<void( T )>;

int main()
{
    Func<void> hello = [] { std::cout << "Hello\n"; };
    hello();
}
Run Code Online (Sandbox Code Playgroud)
  • 那么为什么上面的代码按照我的预期编译和工作呢?
  • 这是一个正确的实现,如果没有,它会是什么样子?

Col*_*mbo 5

或者它只是一个编译器错误?

那.如@TC所述,CWG#577是相关的:

[...]如果更改了C++规则,则对函数模板和类模板的成员函数的处理表达了一些担忧:对于模板参数T,如果函数采用类型的单个参数,T则它将成为无参数函数实例化 T = void

这是一个合理的投诉,但不幸的是,成员函数/成员函数模板和type-id受到了解决方案的同等影响:

非依赖类型void的单个未命名参数组成的参数列表等同于空参数列表.

因此,你的片段都是格式错误的,因为参数的类型确实是依赖的.


这是一个正确的实现,如果没有,它会是什么样子?

没有正确的实施.如果需要具有空参数列表的函数类型,则必须指定独立于模板参数的函数类型.

那么为什么上面的代码按照我的预期编译和工作呢?

我最好的猜测:VC++ void_template_alias_t<T> 确保参数类型不是依赖类型"cv void"之后,但在进行" void- >空列表转换" 之前进行替换.但是,通常很难理解VC++(或任何编译器)在内部如何思考.