开发者问题收集

如何将 std::array 传递给可以接受 std::vector 的函数模板

2021-11-17
489

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

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

2个回答

如果您希望限制模板仅适用于 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();
}
Caleth
2021-11-17

如果您实例化一个数组并采用其大小(即 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();
}

如果值类型的默认初始化成本很高,这当然会出现问题。

eike
2021-11-17