【问题标题】:Problem with variadic template expansion in Visual StudioVisual Studio 中的可变参数模板扩展问题
【发布时间】:2019-09-23 19:41:58
【问题描述】:

这段代码与 gcc 配合得很好:

#include <iostream>
#include <type_traits>
#include <utility>

template <bool... Bs>
struct bool_sequence {};

template <bool... Bs>
using bool_and = std::is_same<
                            bool_sequence<Bs...>,
                            bool_sequence<(Bs || true)...>
                            >;
template <bool... Bs>
using bool_or = std::integral_constant<bool, !bool_and<!Bs...>::value>;

int main(int argc, char* argv[])
{
    std::cout << bool_or<true>::value << std::endl;
    std::cout << bool_or<true, true>::value << std::endl;
    std::cout << bool_or<true, true, true>::value << std::endl;
}

预期输出:1 1 1。 Here live example

但是 VS 2017 输出:0 0 0。 这是 VS 中的错误还是我在这里遗漏了什么?

编辑: VS 2017,v141,cl:19.16.27030.1

谢谢

【问题讨论】:

  • 您能否提供有关您的编译器版本的更多信息?我在 godbolt 上使用 vs 2017 进行的测试没有重现该行为。
  • @StoryTeller: VS 2017 proffessional, v141, cl: 19.16.27030.1
  • 啊哈。考虑到它在 19.14 中有效,我会说你确实遇到了回归。
  • 仅供参考,如果这是您尝试编译的实际代码而不是 MVCE:std::disjunctionstd::conjunction 执行这些相同的操作,并且大多数肯定可以在所有这些编译器版本下工作。跨度>
  • @Frank:是的,std::conjunction 和 std::disjunction 工作严格。但这只是 MVCE,问题是为什么 VS 不能正确编译它。有趣的是,VS 中的 Intellisense 正确显示了展开,但编译器却做错了。

标签: c++ visual-studio templates c++14 c++17


【解决方案1】:

这并不能直接回答我的问题,而只是一种解决方法(实际上不是真正的解决方法,但与上面的 MVCE 相比,实际代码更清洁的解决方案)使用 @Frank 在评论中提出的 std::conjunction/disjunction ,以防其他人出于同样的原因来到这里。

这可以按预期在 VS 上运行:

#include <iostream>
#include <type_traits>
#include <utility>

template <bool... Bs>
using bool_and =
    std::conjunction<std::integral_constant<bool, Bs>...>;

template <bool... Bs>
using bool_or =
    std::disjunction<std::integral_constant<bool, Bs>...>;

int main()
{
    std::cout << bool_or<true>::value << std::endl;
    std::cout << bool_or<true, true>::value << std::endl;
    std::cout << bool_or<true, true, true>::value << std::endl;
}

还有live

【讨论】:

    【解决方案2】:

    为什么不使用 c++17 fold expression:

    #include <iostream>
    #include <type_traits>
    
    template <bool... Bs>
    using bool_and = std::bool_constant<(Bs && ...)>;
    
    template <bool... Bs>
    using bool_or = std::bool_constant<(Bs || ...)>;
    
    int main()
    {
        std::cout << bool_or<true>::value << std::endl;
        std::cout << bool_or<false, false>::value << std::endl;
        std::cout << bool_and<true, false, true>::value << std::endl;
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-12
      • 1970-01-01
      • 2019-05-06
      • 2014-10-30
      • 2013-10-03
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多