【问题标题】:storing arrays of string literals without size - simple template over array size存储没有大小的字符串文字数组 - 简单模板超过数组大小
【发布时间】:2022-06-13 20:02:34
【问题描述】:

我正在探索在没有边车大小信息的情况下存储文字数组(任何类型)的方法。我已经勾勒出了一些方法,但对于每一种方法都有一些挥之不去的问题。这是最简单的方法,模板超过数组大小。请注意,这是一个简单的测试用例,实际的类可能有额外的成员、额外的模板参数和必须提供的模板参数。

template <size_t I>
struct A0 {
    std::array<const char*, I> a;
};

问题是大小与字符串文字分离,使得这些错误太容易了:

// error, not caught
auto a0 = A0<3>{{"1","2"}};

虽然下面的初始化是有效的,因为 C++20 不允许部分 CTAD,如果指定任何模板参数 必须,它就无法工作。它还用样板交换样板:'' 以换取'std::array'。不指定类型CTAD将无法推导出模板大小参数'I'。

auto a0 = A0{std::array{"1","2"}};

是否有扣除指南允许:

auto a0 = A0{{"1","2"}};

【问题讨论】:

  • 更好地编辑原始问题。或者至少删除旧的
  • 如果您想要一些控制和(禁用聚合初始化的某些行为),您可以使用常规构造函数。

标签: c++ templates c++20 c-strings


【解决方案1】:

所以,你问的是auto a0 = A0{{"1","2"}};,但首先这里是auto a0 = A0{"1","2"};的推演指南:

template<typename... Ts>
A0(Ts...) -> A0<sizeof...(Ts)>;

我认为它的作用很清楚。它只是计算给定参数的数量。

对于auto a0 = A0{{"1","2"}};

template<typename T, std::size_t N>
A0(const T(&)[N]) -> A0<N>;

这依赖于这样一个事实,即可以通过模板参数推导将大括号参数推导出为数组类型。这里需要注意的是,大括号参数的所有元素必须具有相同的类型。

然后,在类模板参数推导之后,这两者都依赖于聚合初始化(可以省略额外的大括号)来实际构造类实例。但如果你在类中有构造函数,它的工作原理是一样的。

【讨论】:

    【解决方案2】:

    如果用户指定的参数数量不正确,您可以创建一个模板构造函数,该构造函数与用户定义的推导准则相结合,可以推导出正确的参数计数或导致编译器错误:

    template <size_t I>
    struct A0 {
        template<class ...Args>
        constexpr A0(Args...args)
            : a{ args... }
        {
            static_assert(sizeof...(args) == I, "parameter count does not match array size");
        }
    
        std::array<const char*, I> a;
    };
    
    template<class ...Args>
    A0(Args...args)->A0<sizeof...(args)>;
    
    constexpr A0 a{ "1", "2", "3" };
    constexpr A0<4> a1 { "1", "2", "3" }; // compiler error: parameter count does not match array size
    

    【讨论】:

      猜你喜欢
      • 2022-06-14
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      相关资源
      最近更新 更多