【问题标题】:MSVC lambda with two auto params of same type具有两个相同类型的自动参数的 MSVC lambda
【发布时间】:2018-08-01 19:46:39
【问题描述】:

鉴于以下代码,Visual Studio 的行为似乎与 GCC 和 Clang 不同:

auto f2 = [](auto x, decltype(x) y)
{
  return x + y;
};
f2(1, 2);

Clang 和 GCC 会接受这一点,但 MSVC 会抱怨该消息

error C3536: 'x': 在初始化之前不能使用

是否有一种解决方法可以强制 2 个参数类型相等?

注意:这个问题可以在 Visual Studio 2015、2017 和 Pre-2018 中重现

参见this code on compiler explorer(您可以在其中切换不同的编译器)


编辑:

这段代码的行为并不是人们在阅读它时所期望的:只要 decltype(y) 可转换为 decltype(x),它就会编译,而不仅仅是当它们相等时。

所以,@n.m. @max66 的答案是正确的:第一个是如果你想强制类型相等,第二个是如果你想使用 is_convertible。

我接受了第二个,因为它保留了原始代码行为(尽管原始代码可能是错误的:在我的情况下,比较类型相等性更好)

【问题讨论】:

    标签: visual-studio templates lambda c++14 generic-lambda


    【解决方案1】:

    不完全是你问的,但是......也许你可以将它强加在 lambda 中,使用另一个 lambda

    auto f2 = [] (auto x, auto y)
     { return [](decltype(x) a, decltype(x) b) {return a + b;}(x, y); };
    

    【讨论】:

    • 好主意!但是在这种情况下,f2('c', 2)将编译(比较 char 和 int)。
    • @PascalT。 - 是的;但f2('c', 2) 也将与[](auto x, decltype(x) y) 一起编译(Barry 纠正了我关于这一点的问题)。如果你想让f2('c', 2) 不编译,那是另一种类型的问题。
    • 你是对的。原始代码使用 f('c', 2) 正确编译。我不知道这是不是有意的,虽然:我正在将一些代码移植到 Windows,我需要检查代码的原始意图。
    【解决方案2】:
    auto f2 = [](auto x, auto y)
    {
      static_assert(std::is_same<decltype(x), decltype(y)>::value, 
                    "Argument types must be the same");
      return x + y;
    };
    

    为了更忠实地模拟原始行为,您可以尝试使用 is_convertible 而不是 is_same(但某些 MSVC 版本的 ICE 出于某种原因在其上)。

    【讨论】:

    • 不错!我喜欢它,因为我们还有一个额外的好处,那就是在出现类型错误时提供更人性化的编译器输出
    • 你的答案和@max66 都是正确的,据我说!
    猜你喜欢
    • 2020-11-26
    • 2011-10-15
    • 2022-08-18
    • 2019-04-15
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多