我正在嘗試創建一個函式,該函式將以創建動態分配的二維陣列(矩陣)的方式生成兩個陣列的廣義外積。前兩個引數的型別必須與后兩個引數的型別相同,但前兩個引數的型別不必與后兩個引數的型別相同(例如前兩個引數可以是指標到整數甲板)。這也意味著這兩個陣列的元素不一定必須是相同的型別。至于函式??,它應該是一個lambda函式。唯一的限制是它必須能夠接收這兩個陣列的元素作為引數。函式 ?? 回傳的值的型別可以是任何型別,這種型別將是矩陣的元素。
例子
5 2 8
1 3 6 2
函式 f(x,y)=x 2y
7 11 17 9
4 8 14 6
10 14 20 12
#include <iostream>
#include <vector>
/*I don't know how to make Generalized_Outer_Product accept lambda function*/
template < typename iterator_tip1, typename iterator_tip2, typename tip >
auto Generalized_Outer_Product(iterator_tip1 start_first, iterator_tip1 after_end_first,
iterator_tip2 start_second, iterator_tip2 after_end_second, tip f(tip)) {
using type_of_object_first = typename std::decay < decltype( * start_first) > ::type;
using type_of_object_second = typename std::decay < decltype( * start_second) > ::type;
int n1 = std::distance(start_first, after_end_first);
int n2 = std::distance(start_second, after_end_second);
type_of_object_first ** mat = nullptr;
mat = new int * [n1];
for (int i = 0; i < n1; i )
mat[i] = nullptr;
try {
for (int i = 0; i < n1; i )
mat[i] = new type_of_object_first[n2];
for (int i = 0; i < n1; i ) {
for (int j = 0; j < n2; j ) {
mat[i][j] = f( * start_first, * start_second);
start_second ;
}
start_first ;
start_second -= n2;
}
} catch (...) {
for (int i = 0; i < n1; i )
delete[] mat[i];
delete[] mat;
throw std::range_error("Not enough memory");
}
return mat;
}
int main() {
int n1, n2, x;
std::cin >> n1;
std::vector < int > a, b, c;
for (int i = 0; i < n1; i ) {
std::cin >> x;
a.push_back(x);
}
std::cin >> n2;
for (int i = 0; i < n2; i ) {
std::cin >> x;
b.push_back(x);
}
try {
std::cout << "Generalized Outer Product f(x,y)=x 2y:" << std::endl;
int ** mat = nullptr;
mat = Generalized_Outer_Product(a.begin(), a.end(), b.begin(), b.end(), [](int x, int y) {
return x 2 * y;
});
for (int i = 0; i < n1; i ) {
for (int j = 0; j < n2; j )
std::cout << mat[i][j] << " ";
std::cout << std::endl;
}
for (int i = 0; i < n1; i )
delete[] mat[i];
delete[] mat;
} catch (std::range_error e) {
std::cout << e.what();
}
return 0;
}
你能幫我以正確的方式接受 lambda 函式嗎?
uj5u.com熱心網友回復:
TL博士
只需將引數的型別保持打開狀態,讓編譯器處理無效的引數型別即可;用于decltype確定結果元素型別:
template<class Iterator1, class Iterator2, class Function>
auto GeneralizedOuterProduct(Iterator1 const start1, Iterator1 const end1, Iterator2 const start2, Iterator2 const end2, Function&& f)
{
using ResultType = decltype(f(*start1, *start2));
...
}
附加建議 完整代碼
首先為自己創建一個管理資料生命周期的型別。這簡化了例外處理。如果做得正確,您可以簡單地讓您的例外在GeneralizedProduct函式中未經處理,而不必擔心記憶體泄漏。
下面的類簡單地使用一個std::vector來存盤一行的資料。索引運算子使用向量迭代器允許我們撰寫iter[index]來獲取index對迭代器位置之后的元素元素的參考這一事實。
template<class T>
struct MultiplicationResult
{
public:
using ValueType = T;
using IndexOperatorElement = std::vector<ValueType>::iterator;
using IndexOperatorElementConst = std::vector<ValueType>::const_iterator;
MultiplicationResult(size_t dimension1, std::vector<T>&& data)
: m_dimension1(dimension1)
{
if (data.size() % dimension1 != 0)
{
throw std::runtime_error("invalid data: the number of data elements is not divisible by dimension1");
}
m_dimension2 = data.size() / dimension1;
m_data = std::move(data);
}
IndexOperatorElement operator[](size_t index)
{
return m_data.begin() index * m_dimension2;
}
IndexOperatorElementConst operator[](size_t index) const noexcept
{
return m_data.cbegin() index * m_dimension2;
}
size_t Dimension1() const noexcept
{
return m_dimension1;
}
size_t Dimension2() const noexcept
{
return m_dimension2;
}
private:
std::vector<T> m_data;
size_t m_dimension1;
size_t m_dimension2;
};
現在該GeneralizedProduct函式要做的就是確定結果型別并創建將用作MultiplicationResult.
請注意,我們不會以任何方式限制此處傳遞的函式的型別。如果在給定取消參考的迭代器的情況下無法呼叫傳入引數的呼叫運算子,或者如果結果型別不是可以用作std::vector. 請注意,lambda 是具有呼叫運算子的物件,因此不能分配給result_type(argument_type1, argument_type2). (我認為這種方法比使用更方便std::function<result_type(argument_type1, argument_type2)>:
template<class Iterator1, class Iterator2, class Function>
auto GeneralizedOuterProduct(Iterator1 const start1, Iterator1 const end1, Iterator2 const start2, Iterator2 const end2, Function&& f)
我們只需使用以下方法確定呼叫呼叫運算子的結果型別decltype:
using ResultType = decltype(f(*start1, *start2));
template<class Iterator1, class Iterator2, class Function>
auto GeneralizedOuterProduct(Iterator1 const start1, Iterator1 const end1, Iterator2 const start2, Iterator2 const end2, Function&& f)
{
using ResultType = decltype(f(*start1, *start2));
size_t const n1 = std::distance(start1, end1);
// if an exception happens, data will ensure the elements already allocated get destroyed
std::vector<ResultType> data;
data.reserve(n1 * std::distance(start2, end2));
for (Iterator1 pos1 = start1; pos1 != end1; pos1)
{
for (Iterator2 pos2 = start2; pos2 != end2; pos2)
{
data.push_back(f(*pos1, *pos2));
}
}
return MultiplicationResult(n1, std::move(data)); // C 17 CTAD deduces the template arguments here
}
示例用法(無例外處理:
int main() {
std::vector<int> a{ 5, 2, 8 };
std::vector<int> b{ 1, 3, 6, 2 };
auto result = GeneralizedOuterProduct(a.begin(), a.end(), b.begin(), b.end(), [](int x, int y) { return x 2* y; });
size_t const d1 = result.Dimension1();
size_t const d2 = result.Dimension2();
for (size_t i = 0; i != d1; i)
{
auto innerArray = result[i];
for (size_t j = 0; j != d2; j)
{
std::cout << std::setw(5) << innerArray[j];
}
std::cout << '\n';
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/463125.html
上一篇:如何在Python中列印除二維陣列中第一個串列的第一個元素之外的所有值
下一篇:C-字串陣列的動態記憶體分配問題
