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

时间:2015-10-17 18:34:36

标签: c++ c++11 visual-studio-2015 language-lawyer type-alias

以下代码与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();
}

我认为不允许编译。

我在玩,代码有点复杂。我天真地期望这个工作,但突然意识到这个代码不应该编译,因为你不能编译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();
}
  • 那么为什么上面的代码会按照我的预期进行编译和工作?
  • 这是一个正确的实现,如果没有,它会是什么样的?

1 个答案:

答案 0 :(得分:5)

  

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

这。如@ T.C。所述,CWG #577是相关的:

  那里有[p]   对功能模板的处理表达了一些担忧   如果更改了C ++规则,则为类模板的成员函数:   对于模板参数T是一个函数采用单个参数   类型T如果被实例化,则成为无参数函数   T = void

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

  

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

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

  

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

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

  

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

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