我想創建一個const std::vector包含其他兩個const std::vector相同型別的所有元素。由于向量是我無法使用連接兩個 std::vectors中提到的方法const逐步將它與兩者連接起來。const std::vector
#include <iostream>
#include <vector>
int main()
{
const std::vector<int> int_a{0,1};
const std::vector<int> int_b{2,3};
const std::vector<int> all_ints;
for (int i: all_ints)
std::cout << i << ' ';
return 0;
}
對于上面的示例,我想以all_ints輸出為0 1 2 3.
那怎么可能呢?
uj5u.com熱心網友回復:
創建一個函式,它接受其他兩個向量,創建第三個向量,插入前兩個向量的值,按值回傳結果。然后將其分配給您的 const 向量:
const std::vector<int> int_a{0,1};
const std::vector<int> int_b{2,3};
const std::vector<int> all_ints = concat(int_a, int_b);
uj5u.com熱心網友回復:
我實際上不知道像這樣創建 const 向量的本質是什么。但是一個簡單的技巧是創建一個臨時的非常量向量并用前兩個向量填充它,然后創建最終的 const 向量。例如:
const std::vector<int> int_a{0,1};
const std::vector<int> int_b{2,3};
std::vector<int> middle(int_a);
middle.insert(middle.begin(),int_b.begin(),int_b.end());
const std::vector<int> all_ints(middle);
正如評論中所建議的,最后一行可以寫成:
const std::vector<int> all_ints = std::move(middle);
uj5u.com熱心網友回復:
正如@Ayxan Haqverdili的回答中已經提到的,您可以創建一個連接函式,用于初始化您的向量。
我為這樣的功能提出了以下實作:
template <template <typename, typename> typename C, typename ... Args>
C<Args...> concat(const C<Args...> & lhs, const C<Args...> & rhs)
{
C<Args...> res(lhs.cbegin(), lhs.cend());
res.insert(res.cend(), rhs.cbegin(), rhs.cend());
return res;
}
注意:這個實作被推廣到所有標準庫序列容器,除了std::array.
然后可以這樣使用:
const std::vector<int> a {1, 2, 3};
const std::vector<int> b {4, 5};
const std::vector<int> ab = concat(a, b);
現場示例在這里
另一個更簡單的版本可能是:
template <typename C>
C concat(const C & lhs, const C & rhs)
{
C res(lhs.size() rhs.size());
typename C::iterator it = std::copy(lhs.cbegin(), lhs.cend(), res.begin());
std::copy(rhs.cbegin(), rhs.cend(), it);
return res;
}
現場示例在這里
uj5u.com熱心網友回復:
如果您只是想遍歷兩個向量,則可以使用自定義視圖連接器來完成。以下比創建(和銷毀)另一個容器只是為了迭代兩個范圍要有效得多。
#include <iostream>
#include <array>
#include <ranges>
#include <vector>
#include <utility>
template<typename T1, typename T2>
auto concat_view(T1& lhs, T2& rhs)
{
static_assert(std::is_same_v<std::decay_t<T1>, std::decay_t<T2>>);
using T1_ = std::remove_reference_t<T1>;
using T2_ = std::remove_reference_t<T2>;
if constexpr (std::is_const_v<T1_> || std::is_const_v<T2_>)
{
using Iter = typename std::decay_t<T1>::const_iterator;
return std::array<std::ranges::subrange<Iter>, 2>{std::as_const(lhs), std::as_const(rhs)} | std::views::join;
}
else
{
using Iter = typename std::decay_t<T1>::iterator;
return std::array<std::ranges::subrange<Iter>, 2>{lhs, rhs} | std::views::join;
}
}
int main()
{
std::vector<int> v1{1,2,3}, v2{4,5,6};
for (int& val : concat_view(v1, v2))
val;
for (const auto& val : concat_view(std::as_const(v1), v2))
std::cout << val << '\n';
return 0;
}
uj5u.com熱心網友回復:
這是另一個實作,也可以很容易地修改,甚至all_ints在將來修改 的內容。它不需要最新的 c 版本。
#include <vector>
#include <algorithm>
int main()
{
const std::vector<int> int_a{ 0,1 };
const std::vector<int> int_b{ 2,3 };
const std::vector<int> all_ints(int_a.size() int_b.size());
std::vector<int>& all_intsr = const_cast<std::vector<int>&>(all_ints);
std::copy(int_b.begin(), int_b.end(), std::copy(int_a.begin(), int_a.end(), all_intsr.begin()));
}
這利用了能夠合法地將 aconst vector&轉換為vector具有以下限制的 a 來防止 UB。不得修改矢量物件。這不包括非 const 向量所擁有的內容。既不修改begin()也不end()修改矢量物件。稍后修改它的元素也是合法的,例如這樣。
all_intsr[3]=42;
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/531474.html
標籤:C 模板stl常数宣言
