【问题标题】:static_assert each parameter's size in parameter packstatic_assert 参数包中每个参数的大小
【发布时间】:2018-12-12 05:34:14
【问题描述】:

我正在尝试检查参数包中的每个参数是否可以存储在 8 个字节内(sizeof

我有函数签名:

template <typename Return, typename... Arguments>
inline auto invoke(std::uint64_t hash, Arguments... arguments) -> Return

使用折叠表达式,我试过了:

static_assert((sizeof(arguments) <= 8 && ...));

使用unexpected token '...', expected 'expression' 编译失败 - 我认为它无效或不正确?

使用 C++20 的概念和约束,我假设类似的东西是可能的?

template <typename Return, typename... Arguments> requires (sizeof(arguments) <= 8 || ...)
inline auto invoke(std::uint64_t hash, Arguments... arguments) -> Return

我假设有一种方法可以使用标准库来检查一个类型是否适合 std::uint64_t 说呢?

【问题讨论】:

  • 你忘记了一对额外的()static_assert(((sizeof(arguments) &lt;= 8) &amp;&amp; ...));。我们应该作为一个错字关闭吗?
  • 看来你是对的@HolyBlackCat - 虽然理想情况下我很想知道实现这一点的最佳方法,比如使用 C++20 概念或其他东西?
  • 你应该编辑问题以澄清。

标签: c++ c++17 c++20


【解决方案1】:

使用 C++20 概念,有很多方法可以实现所需的行为。例如:

template <typename T, size_t N>
concept bool SizeLessEqual = sizeof(T) <= N;

template <SizeLessEqual<8>... Types>
void f() { }

int main() {
    f<bool, char, int, double>();
    f<std::string>();  // error
}

现场演示:https://wandbox.org/permlink/Q9tifNVplsx9BjGN

另一种选择是您的解决方案:

template <typename... Types> requires ((sizeof(Types) <= 8) && ...) 
void f() { }

或者,例如:

template <typename... Types> requires (std::max({ sizeof(Types)... }) <= 8) 
void f() { }

【讨论】:

    【解决方案2】:

    试试这个方法:

    #include <cstdint>
    #include <utility>
    template <typename... Arguments>
    auto invoke(std::uint64_t hash, Arguments... arguments)
    {
        auto check = []( auto&& argument )
        {
            static_assert( sizeof(argument) <= 8, "size too large" );
            return 0;
        };
        auto dummy = { 0, ( check(std::forward<Arguments>(arguments)), 0) ... };
        return 0;
    }
    
    int main()
    {
        invoke( 0UL, '1' );
        invoke( 0UL, '1', 2 );
        invoke( 0UL, '1', 2, 3UL );
        //invoke( 0UL, '1', 2, 3UL, static_cast<long double>(1.0) );
        return 0;
    }
    

    使用逗号运算符和 initializer_list 来解决问题。

    使用 C++17,我们可以进一步将代码修剪为:

    template <typename... Arguments>
    auto invoke(std::uint64_t hash, Arguments... arguments)
    {
        auto check = []( auto&& argument )
        {
            static_assert( sizeof(argument) <= 8, "size too large" );
        };
        (check(std::forward<Arguments>(arguments)), ...);
    }
    

    利用折叠表达式。


    我不明白反对意见,但由于这是我在 stackoverflow 上的最后一篇文章,我在 wandbox 上传了一个实时示例:https://wandbox.org/permlink/NZbqpRaTs2TFOCwG

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-24
      • 2020-07-05
      • 1970-01-01
      • 2017-07-06
      • 2014-12-06
      • 2021-01-31
      • 2015-03-31
      • 2011-09-22
      相关资源
      最近更新 更多