【问题标题】:Unexpected behavior with template type alias in VS2015VS2015 中模板类型别名的意外行为
【发布时间】:2016-01-16 08:52:21
【问题描述】:

以下代码使用 VS15 Community 编译并打印出“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&lt;void&gt;(或者我错了吗?)。

  • 我找到神奇的解决方法了吗?
  • 这是 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();
}
  • 那么为什么上面的代码可以按我最初的预期编译和工作?
  • 这是一个正确的实现,如果不是,它会是什么样子?

【问题讨论】:

  • foo(void)using X = void; foo(X); 之间存在天壤之别。如果其他编译器接受这一点,我会感到惊讶。
  • 哦,我太确定了。标准规定“参数列表(void) 等效于空参数列表。”,但没有指定(void) 是文字文本。并且没有专门的语法产生,g++和Visual C++都编译void foo(X),其中Xvoid的名字,它们编译调用foo()
  • 也许我最好明确指出,(void) 的解释是指一个函数,其中单个参数的 type 实际上是 void,然后表示一个没有参数的函数,不能很好地与使用参数调用函数的模板代码一起工作,即它是不切实际的。然而,MSVC 和 MinGW g++ 都接受非模板 foo(My_void) 并调用 foo()。 :(
  • @Cheersandhth.-Alf 在DR 577 之后,规则是“由一个非依赖类型void 的单个未命名参数组成的参数列表相当于一个空参数列表”。跨度>
  • @T.C.:所以,这在 C++14 中发生了变化。 DR 表明 C++11 和更早版本的自然阅读,因为 (void) 是文字文本(不允许 typedef),是那些版本的正确阅读。谢谢!

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


【解决方案1】:

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

那个。正如@T.C. 所提到的,CWG #577 是相关的:

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

这是一个合理的投诉,但对您来说很不幸,成员函数/成员函数模板和 type-id 受到该决议的同等影响:

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

因此,您的两个 sn-ps 格式都不正确,因为参数的类型确实是依赖的。


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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多