【问题标题】:How to pass a std::array to a function template which can accept std::vector如何将 std::array 传递给可以接受 std::vector 的函数模板
【发布时间】:2021-12-28 08:57:09
【问题描述】:

我正在尝试写一个模板,它可以接受一些序列容器:

template <typename S,
          typename = std::enable_if_t<
              std::is_same<S, std::array<typename S::value_type>, S::size()>::value ||
              std::is_same<S, std::vector<typename S::value_type>>::value>>
std::string arr2String(const S& seqContainer) {
    std::stringstream res;
    for (const auto& element : seqContainer) {
        res << element << "|";
    }
    return res.str();
}

但是,由于S::size(),无法编译。显然,没有这样的事情。

是否可以做这样一个模板函数,可以处理std::vectorstd::array

【问题讨论】:

  • std::vectorstd::array?
  • 我建议你根本不要传递容器,而是像标准库本身那样做:传递迭代器范围。
  • 为什么必须是数组或向量?您的代码适用于 std::arrays、向量、列表、双端队列、字符串、C 数组和跨度。为什么仅限于 std::arrays 和向量?
  • @Yves 但为什么不删除第二部分而只保留template&lt;typename S&gt;
  • 最简单、最简单、最便携、最老派的方法是接受一对迭代器。一路 C++98。

标签: c++ arrays templates c++14


【解决方案1】:

如果您想限制您的模板仅适用于 std::arraystd::vector,您可以编写一些辅助特征

template <typename>
struct is_array : std::false_type {}

template <typename T, std::size_t N>
struct is_array<std::array<T, N>> : std::true_type {}

template <typename>
struct is_vector : std::false_type {}

template <typename... Ts>
struct is_vector<std::vector<Ts...>> : std::true_type {}

template <typename S,
          typename = std::enable_if_t<
              is_array<S>::value ||
              is_vector<S>::value>>
std::string arr2String(const S& seqContainer) {
    std::stringstream res;
    for (const auto& element : seqContainer) {
        res << element << "|";
    }
    return res.str();
}

否则你可以在更一般的东西上使用 SFINAE

template <typename S, typename = typename S::value_type>
std::string arr2String(const S& seqContainer) {
    std::stringstream res;
    for (const auto& element : seqContainer) {
        res << element << "|";
    }
    return res.str();
}

【讨论】:

    【解决方案2】:

    如果您实例化一个数组并获取其大小(即 constexpr),您的代码实际上可以被编译。

    template <typename S,
            typename = std::enable_if_t<
                std::is_same<S, std::array<typename S::value_type, S{}.size()>>::value ||
                std::is_same<S, std::vector<typename S::value_type>>::value>>
    std::string arr2String(const S& seqContainer) {
        std::stringstream res;
        for (const auto& element : seqContainer) {
            res << element << "|";
        }
        return res.str();
    }
    

    如果你的值类型的默认初始化很昂贵,这当然会有问题。

    【讨论】:

    • 哦..好的,我明白了。
    • “如果你的值类型的默认初始化很昂贵,这当然会有问题。” - 为什么?这里没有在运行时初始化。
    • 你说得对,我不知何故认为这可以通过重新排列 or 表达式来解决,但所有子表达式当然必须是有效的。
    猜你喜欢
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    相关资源
    最近更新 更多