Я изучаю шаблоны C++ и читаю < < C++ Templates: The Complete Guide >>. Я не понимаю, протекающего о шаблоне выражения:Expression Templates - C++ Templates: Полное руководство
Этот код выглядит следующим образом:
//exprarray.h
#include <stddef.h>
#include <cassert>
#include "sarray.h"
template<typename T>
class A_Scale
{
public:
A_Scale(T const& t):value(t){}
T operator[](size_t) const
{
return value;
}
size_t size() const
{
return 0;
}
private:
T const& value;
};
template<typename T>
class A_Traits
{
public:
typedef T const& exprRef;
};
template<typename T>
class A_Traits<A_Scale<T> >
{
public:
typedef A_Scale<T> exprRef;
};
template<typename T,typename L1,typename R2>
class A_Add
{
private:
typename A_Traits<L1>::exprRef op1;
typename A_Traits<R2>::exprRef op2;
public:
A_Add(L1 const& a,R2 const& b):op1(a),op2(b)
{
}
T operator[](size_t indx) const
{
return op1[indx] + op2[indx];
}
size_t size() const
{
assert(op1.size()==0 || op2.size()==0 || op1.size() == op2.size());
return op1.size() != 0 ? op1.size() : op2.size();
}
};
template<typename T,typename L1,typename R2>
class A_Mul
{
private:
typename A_Traits<L1>::exprRef op1;
typename A_Traits<R2>::exprRef op2;
public:
A_Mul(L1 const& a,R2 const& b):op1(a),op2(b)
{
}
T operator[](size_t indx) const
{
return op1[indx] * op2[indx];
}
size_t size() const
{
assert(op1.size()==0 || op2.size()==0 || op1.size() == op2.size());
return op1.size() != 0 ? op1.size():op2.size();
}
};
template<typename T,typename Rep = SArray<T> >
class Array
{
public:
explicit Array(size_t N):expr_Rep(N){}
Array(Rep const& rep):expr_Rep(rep){}
Array& operator=(Array<T> const& orig)
{
assert(size() == orig.size());
for (size_t indx=0;indx < orig.size();indx++)
{
expr_Rep[indx] = orig[indx];
}
return *this;
}
template<typename T2,typename Rep2>
Array& operator=(Array<T2,Rep2> const& orig)
{
assert(size() == orig.size());
for (size_t indx=0;indx<orig.size();indx++)
{
expr_Rep[indx] = orig[indx];
}
return *this;
}
size_t size() const
{
return expr_Rep.size();
}
T operator[](size_t indx) const
{
assert(indx < size());
return expr_Rep[indx];
}
T& operator[](size_t indx)
{
assert(indx < size());
return expr_Rep[indx];
}
Rep const& rep() const
{
return expr_Rep;
}
Rep& rep()
{
return expr_Rep;
}
private:
Rep expr_Rep;
};
template<typename T,typename L1,typename R2>
Array<T,A_Add<T,L1,R2> >
operator+(Array<T,L1> const& a,Array<T,R2> const& b)
{
return Array<T,A_Add<T,L1,R2> >(A_Add<T,L1,R2>(a.rep(),b.rep()));
}
template<typename T,typename L1,typename R2>
Array<T,A_Mul<T,L1,R2> >
operator*(Array<T,L1> const& a,Array<T,R2> const& b)
{
return Array<T,A_Mul<T,L1,R2> >(A_Mul<T,L1,R2>(a.rep(),b.rep()));
}
template<typename T,typename R2>
Array<T,A_Mul<T,A_Scale<T>,R2> >
operator*(T const& a,Array<T,R2> const& b)
{
return Array<T,A_Mul<T,A_Scale<T>,R2> >(A_Mul<T,A_Scale<T>,R2>(A_Scale<T>(a),b.rep()));
}
Тест Код:
//test.cpp
#include "exprarray.h"
#include <iostream>
using namespace std;
template <typename T>
void print (T const& c)
{
for (int i=0; i<8; ++i) {
std::cout << c[i] << ' ';
}
std::cout << "..." << std::endl;
}
int main()
{
Array<double> x(1000), y(1000);
for (int i=0; i<1000; ++i) {
x[i] = i;
y[i] = x[i]+x[i];
}
std::cout << "x: ";
print(x);
std::cout << "y: ";
print(y);
x = 1.2 * x;
std::cout << "x = 1.2 * x: ";
print(x);
x = 1.2*x + x*y;
std::cout << "1.2*x + x*y: ";
print(x);
x = y;
std::cout << "after x = y: ";
print(x);
return 0;
}
Мои вопросы почему A_Traits для A_Scale является значение не Справка.
template<typename T>
class A_Traits
{
public:
typedef T const& exprRef;
};
template<typename T>
class A_Traits<A_Scale<T> >
{
public:
typedef A_Scale<T> exprRef;
};
Причина из книги следующим образом:
Это необходимо по следующим причинам: В общем, мы можем объявить их как ссылки, поскольку большинство временных узлов связаны в верхнем уровне и, следовательно, жить до конца оценки этого полного выражения. Единственным исключением являются узлы A_Scalar. Они связаны внутри операторных функций и могут не доживать до конца оценки полного выражения. Таким образом, чтобы избежать того, что члены ссылаются на скаляры, которые больше не существуют, для скаляров операнды должны копироваться «по значению».
Более подробно, пожалуйста, обратитесь к главе 18 C++ Templates: The Complete Guide
Больше контекста поможет. Что означает «A_Scalar»? По крайней мере, вы можете предоставить страницу и версию книги, которую вы читаете. –
О, извините, вы можете сослаться на эту ссылку: [Google books] (https://books.google.com/books?id=yQU-NlmQb_UC&pg = PA331 и сжиженный газ = PA331 & дк = в + общем + мы + может + объявить + их + до + будет + ссылки +, потому что + самое + временные узлы + + являются + связаны + в + с + верхнего уровня + выражение + и + поэтому + live + до & source = bl & ots = EfoJ31UyEW & sig = AdpZxmEqmUfHcmJ6wrfGUp4Z7TU & hl = en & sa = X & ved = 0ahUKEwiGw67RsrPPAhUQ8GMKHVhIAegQ6AEIHDAA # v = onepage & q & f = false) – Bobo
@Bobo Вся информация, относящаяся к ответе на вопрос, должна быть в вопросе. Внешние ссылки предназначены для «если вы хотите узнать больше».Пожалуйста, отредактируйте вопрос, который отвечает без внешних ссылок, которые могут стать недействительными в будущем. Эта должность и любая должность СО должны оставаться актуальными независимо от наличия внешних ресурсов. – bolov