【问题标题】:How do I make these fold expressions work?如何使这些折叠表达式起作用?
【发布时间】:2021-08-05 04:36:10
【问题描述】:

我不明白为什么这不起作用:

template <typename ... Types>
void func()
{

    (std::cout << typeid(Types).name(), ...) ; // Syntax error, unexpected token '...', expected 'expression'
    (static_assert(std::is_integral_v<Types>, "Type must be integral type"), ...); // Syntax error: unexpected token 'static_assert', expected 'expression'
}
int main()
{
    func<int, short>();

}

我的理解是编译器基本上应该去:

(static_assert(std::is_integral_v<Types>, "Error message"), ...)

逗号是一个运算符,对于参数包中的每种类型,应该重复运算符之前的内容。为什么这不起作用?

【问题讨论】:

    标签: c++ templates fold-expression


    【解决方案1】:

    你的第一个语法错误可能是由于没有使用 C++17 作为折叠表达式引入的结果。 我尝试用 C++14 编译你的代码,得到了同样的语法错误。

    (std::cout << typeid(Types).name(), ...);  // needs C++17, Syntax error with C++14
    

    第二个可以改写成这样:

    static_assert((std::is_integral_v<Types> && ...), "Type must be integral type");
    

    【讨论】:

      【解决方案2】:

      折叠表达式不能包含(无括号)优先级低于强制转换的运算符。

      所以要么添加括号:((std::cout &lt;&lt; typeid(Types).name()), ...);

      或者折叠&lt;&lt; 代替:(std::cout &lt;&lt; ... &lt;&lt; typeid(Types).name());


      至于static_assert,是声明而不是表达式,所以不能折叠。

      使用一个大的static_assert,带有&amp;&amp;-fold 表达式:

      static_assert((std::is_integral_v<Types> && ...), "Type must be integral type")
      

      【讨论】:

        【解决方案3】:

        运算符&lt;&lt; 要求将... 置于运算符之间。 static_assert 不是表达式,因此折叠表达式无济于事。解决方法是使用单个static_assert 创建一个专用的检查函数,并调用此函数折叠内置运算符, 调用:

        #include <iostream>
        #include <typeinfo>
        #include <type_traits>
        
        template<typename x_Type>
        constexpr void is_integral_check(void) noexcept
        {
            static_assert(::std::is_integral_v<x_Type>, "Type must be an integral type.");
            return;
        }
        
        template<typename ... x_Types>
        void func()
        {
            (::std::cout << ... << typeid(x_Types).name());
            (is_integral_check<x_Types>(), ...);
        }
        
        int main()
        {
            func<int, short>();
        }
        

        https://godbolt.org/z/5G4xxc15s

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-19
          • 2023-03-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多