实现支持任意数量std::array的MyCat函数及编译错误解决
MyCat Template Function for Google Test Let's get your MyCat function working properly so it passes the Google Test case you've written. Your goal is to concatenate multiple identical-type/size std::arrays into a single larger array, but your current code has syntax and logic issues we'll address step by step.
First: Break Down the Compilation Errors
Your original code has a few critical mistakes that are causing the compiler to fail:
- Invalid parameter pack declaration:
(std::array<T, N>) ... arraysis not valid C++. Parameter packs for templates should be declared asstd::array<T, N>... arrays(adding aconst&is better for performance to avoid unnecessary copies). - Miswritten return type: The
decltypeusage here is redundant and incorrect. You can directly specify the return type asstd::array<T, N * sizeof...(arrays)>since we know the total size upfront (each array's size multiplied by the number of arrays). - Broken element copying logic: Lines like
T* = array.begin();(missing a variable name) andwhile(!T)(invalid condition) don't make sense for iterating over array elements.
Correct Implementation (C++14 Compatible)
This version works with C++14 and later, and efficiently copies elements from each input array:
#include <array> #include <algorithm> #include <utility> template<class T, size_t N> auto MyCat(const std::array<T, N>&... arrays) -> std::array<T, N * sizeof...(arrays)> { std::array<T, N * sizeof...(arrays)> retArray; size_t current_pos = 0; // Use a dummy initializer_list to expand the parameter pack (C++14 trick) (void)std::initializer_list<int>{ (std::copy(arrays.begin(), arrays.end(), retArray.begin() + current_pos), current_pos += N, 0)... }; return retArray; }
Simplified C++17 Version (Using Fold Expressions)
If you're using C++17 or newer, fold expressions make the code cleaner and more readable:
#include <array> #include <algorithm> template<class T, size_t N> std::array<T, N * sizeof...(arrays)> MyCat(const std::array<T, N>&... arrays) { std::array<T, N * sizeof...(arrays)> retArray; size_t current_pos = 0; // C++17 fold expression to iterate over each input array ((std::copy(arrays.begin(), arrays.end(), retArray.begin() + current_pos), current_pos += N), ...); return retArray; }
Key Details Explained
- Automatic Template Deduction: The template deduces
T(the element type) andN(the size of each input array) automatically from the arguments you pass—no need to specify them manually. - Parameter Pack Expansion: Both versions use different techniques to iterate over every array in the parameter pack:
- C++14: Uses a dummy
std::initializer_listto trigger expansion of the copy logic for each array. - C++17: Uses a fold expression to chain the copy operations directly, making the code more intuitive.
- C++14: Uses a dummy
- Safe Element Copying:
std::copyis used to safely copy all elements from each input array into the correct position in the result array (starting atcurrent_pos, which increments byNafter each array is processed).
Verifying the Test Case
Your Google Test case will now pass without modifications:
TEST(MyCat, CheckOn2Arrays){ std::array<float, 3> vec1{1.0f, 2.0f, 3.0f}; std::array<float, 3> vec2{4.0f, 5.0f, 6.0f}; std::array<float, 6> r = MyCat(vec1, vec2); EXPECT_EQ(r[0], 1.0f); EXPECT_EQ(r[1], 2.0f); EXPECT_EQ(r[2], 3.0f); EXPECT_EQ(r[3], 4.0f); EXPECT_EQ(r[4], 5.0f); EXPECT_EQ(r[5], 6.0f); }
The compiler will deduce T = float and N = 3 from vec1 and vec2, and the return type will be std::array<float, 6> as expected.
内容的提问来源于stack exchange,提问作者Yarik2308

