I'm trying to write a template, which can accept some sequence containers:
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();
}
However, this can't be compiled because of S::size()
. Obviously, there is no such a thing.
Is it possible to make such a template function, which can handle std::vector
and std::array
?
CodePudding user response:
If you want to restrict your template to work for only std::array
or std::vector
, you can write some helper traits
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();
}
Otherwise you can SFINAE on something more general
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();
}
CodePudding user response:
Your code could in fact be compiled if you instantiated an array and took its size, which is 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();
}
This of course would be problematic if default initialization of your value type is expensive.