代码之家  ›  专栏  ›  技术社区  ›  康桓瑋

组合范围适配器和std::source_location得到了奇怪的结果

  •  1
  • 康桓瑋  · 技术社区  · 3 年前

    考虑一下 following useless code :

    #include <ranges>
    #include <source_location>
    #include <iostream>
    
    int main() {
      auto lines = std::views::iota(0, 5)
                 | std::views::transform(
                    [](int, const std::source_location& location = std::source_location::current()) 
                    { return location.line(); }
                   );
      for (const auto& line : lines)
        std::cout << line << "\n";
    }
    

    MSVC以奇怪的错误消息拒绝:

    (7): error C2676: binary '|': 'std::ranges::iota_view<_Ty1,_Ty2>' does not define this operator or a conversion to a type acceptable to the predefined operator
                with
                [
                    _Ty1=int,
                    _Ty2=int
                ]
    

    GCC输出奇怪的行号 61 无论哪一排 std::source_location::current() 位于:

    61
    61
    61
    61
    61
    

    上面的代码格式正确吗?如果是,这是否意味着MSVC和GCC都有漏洞?

    0 回复  |  直到 3 年前
        1
  •  3
  •   Barry    3 年前

    gcc是正确的,程序是完全有效的。

    GCC输出奇怪的行号 61 无论哪一排 std::source_location::current() 位于:

    这是因为默认的函数参数, current() ,在函数的点进行评估 呼叫 ,这与函数所在的位置无关 宣布 .

    此函数由调用 transform_view s iterator s operator*() 。但不是直接通过 操作人员 ,那个接线员要打电话 invoke 它本身需要做大量的工作来确保它被正确调用。以及libstdc++的实现中的实际最终重载 援引 被称为…哦,看看这个,它是 bits/invoke.h:61 :

    template<typename _Res, typename _Fn, typename... _Args>
      constexpr _Res
      __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
      { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
    

    如果不只是打印行号 source_location 给你,你也打印了文件 名称 :

    auto lines = std::views::iota(0, 5)
               | std::views::transform(
                  [](int, const std::source_location& location = std::source_location::current()) 
                  { return fmt::format("{}:{}", location.file_name(), location.line()); }
                 );
    
    fmt::print("{}\n", lines);
    

    打印包含字符串的范围 /opt/compiler-explorer/gcc-trunk-20210817/include/c++/12.0.0/bits/invoke.h:61 ,五次。