C++;从函数返回更精确的两个模板参数? 我很好奇,在C++中有没有办法做到这一点。假设我有一个模板向量类: template <typename T> class vector { public: vector(T a, T b, T c) : x(a), y(b), z(c) {} T x,y,z; }; 模板 类向量{ 公众: 向量(ta,tb,tc):x(a),y(b),z(c){ tx,y,z; };
然后我有一个模板化的加法运算符:C++;从函数返回更精确的两个模板参数? 我很好奇,在C++中有没有办法做到这一点。假设我有一个模板向量类: template <typename T> class vector { public: vector(T a, T b, T c) : x(a), y(b), z(c) {} T x,y,z; }; 模板 类向量{ 公众: 向量(ta,tb,tc):x(a),y(b),z(c){ tx,y,z; };,c++,templates,C++,Templates,然后我有一个模板化的加法运算符: template <typename A, typename B> vector<A> operator +(const vector<A> &a, const vector<B> &b) { return vector<A>(a.x+b.x, a.y+b.y, a.z+b.z); } 模板 向量运算符+(常数向量&a,常数向量&b){ 返回向量(a.x+b.x,a.y+b
template <typename A, typename B>
vector<A> operator +(const vector<A> &a, const vector<B> &b) {
return vector<A>(a.x+b.x, a.y+b.y, a.z+b.z);
}
模板
向量运算符+(常数向量&a,常数向量&b){
返回向量(a.x+b.x,a.y+b.y,a.z+b.z);
}
我很好奇是否有可能修改这个操作符,使结果是A和B两种类型中的哪一种更精确,除了手动专门化它
例如:
vector<float> + vector<double> would produce a vector<double>,
vector<long double> + vector<float> would produce a vector<long double>
vector+vector将生成一个向量,
向量+向量会产生一个向量
我猜C++中没有自动支持,但我想我会问。 你永远也无法完成这个:
vector+vector将生成一个向量
无需大量的欺骗或返回指向您自己设计的小控件的指针,因为
operator+
必须返回编译时已知的类型。您要求返回在运行时确定的类型。在C++0x中,您可以说:
template <typename A, typename B>
auto operator +(const vector<A> &a, const vector<B> &b) -> vector<decltype(a.x + b.x)>
{
//...
}
模板
auto operator+(const vector库的形式没有任何内置的支持,但是您可以使用条件(?:
)操作符来实现这一点
在回答另一个问题时,Johannes Schaub发表了一篇文章,很好地总结了逻辑。有了这个模板,你应该能够写:
template <typename A, typename B>
vector< typename promote<A, B>::type >
operator+(const vector<A> &a, const vector<B> &b)
{
return vector< typename promote<A, B>::type >(a.x+b.x, a.y+b.y, a.z+b.z);
}
模板
vector
运算符+(常数向量和a、常数向量和b)
{
返回向量(a.x+b.x,a.y+b.y,a.z+b.z);
}
使用模板专门化有一种相对简单的方法可以做到这一点
template< typename A >
struct TypePrecision {
static const int precisionLevel;
};
template< typename A >
const int TypePrecision< A >::precisionLevel = 0;
template<>
struct TypePrecision< float > {
static const int precisionLevel;
};
template<>
struct TypePrecision< long float > {
static const int precisionLevel;
};
template<>
struct TypePrecision< double > {
static const int precisionLevel;
};
template<>
struct TypePrecision< long double > {
static const int precisionLevel;
};
template<>
const int TypePrecision< float >::precisionLevel = 1;
template<>
const int TypePrecision< long float >::precisionLevel = 2;
template<>
const int TypePrecision< double >::precisionLevel = 3;
template<>
const int TypePrecision< long double >::precisionLevel = 4;
模板
结构类型精度{
静态常数精度级;
};
模板
const int TypePrecision::precisionLevel=0;
模板
结构类型精度{
静态常数精度级;
};
模板
结构类型精度<长浮点>{
静态常数精度级;
};
模板
结构类型精度{
静态常数精度级;
};
模板
结构类型精度<长双精度>{
静态常数精度级;
};
模板
const int TypePrecision::precisionLevel=1;
模板
const int TypePrecision::precisionLevel=2;
模板
const int TypePrecision::precisionLevel=3;
模板
const int TypePrecision:精度级别=4;
然后使用它创建一个更高精度的类型
template < typename A , typename B >
struct HigherPrecisionType
{
static const int APrecision;
static const int BPrecision;
};
template < typename A , typename B >
const int HigherPrecisionType< A, B >::APrecision= TypePrecision< A >::precisionLevel;
template < typename A , typename B >
const int HigherPrecisionType< A, B >::BPrecision= TypePrecision< B >::precisionLevel;
模板
结构高精度类型
{
静态常数精度;
静态常数int b精度;
};
模板
const int HigherPrecisionType::APrecision=TypePrecision::precisionLevel;
模板
const int HigherPrecisionType::BPrecision=TypePrecision::precisionLevel;
我不知道如何比较这些来获得专业化中的typedef和适当的typedef。但是我希望你能理解这个想法,Andrei Alexandrescu在2001年4月1日的DDJ文章中讨论了这一点
简言之,一般问题非常复杂
Andrei使用了80行支持代码,这些代码又依赖于Loki库
干杯。通过使用函数重载,您可以在一定程度上实现您的目标。这意味着除了通用的:
template <typename A, typename B>
vector<A> operator +(const vector<A> &a, const vector<B> &b) {
return vector<A>(a.x+b.x, a.y+b.y, a.z+b.z);
}
模板
向量运算符+(常数向量&a,常数向量&b){
返回向量(a.x+b.x,a.y+b.y,a.z+b.z);
}
还可以为特定类型声明重载,然后使用这些重载,而不是一般制造的重载:
vector<double> operator +(const vector<float> &a, const vector<double> &b) {
return vector<double>(a.x+b.x, a.y+b.y, a.z+b.z);
}
向量运算符+(常量向量&a,常量向量&b){
返回向量(a.x+b.x,a.y+b.y,a.z+b.z);
}
您的另一个选择是在向量模板上为所需的类型实现转换运算符。使浮点向量能够通过运算符返回双向量。是的。以下是C++03方法:
template < typename T1, typename T2 >
struct which_return;
template < typename T >
struct which_return<T,T> { typedef std::vector<T> type; };
template < >
struct which_return<int,double> { typedef std::vector<double> type; };
template < >
struct which_return<double,int> : which_return<int,double> {};
// etc...
template < typename T1, typename T2 >
typename which_return<T1,T2>::type operator+ (std::vector<T1> const&, std::vector<T2> const&)
{
// ...
}
模板
返回的结构;
模板
返回{typedef std::vector type;}的结构;
模板<>
返回{typedef std::vector type;}的结构;
模板<>
结构which_return:which_return{};
//等等。。。
模板
返回的类型名称::类型运算符+(std::vector const&,std::vector const&)
{
// ...
}
显然,如果你可以,你可以用C++ 0x方式来做。 模式“类型选择”(在“现代C++设计中阅读”)可以在这里有用。
template <bool flag, typename T, typename U>
struct Select {
typedef T Result;
};
template <typename T, typename U>
struct Select<false, T, U> {
typedef U Result;
};
...
template <typename A, typename B>
vector<Select<sizeof(A) > sizeof(B), A, B>::Result> operator +(const vector<A> &a, const vector<B> &b) {
return vector<Select<sizeof(A) > sizeof(B), A, B>::Result>(a.x+b.x, a.y+b.y, a.z+b.z);
}
模板
结构选择{
T型结果;
};
模板
结构选择{
typedef-U结果;
};
...
模板
向量::结果>运算符+(常量向量&a,常量向量&b){
返回向量::结果>(a.x+b.x,a.y+b.y,a.z+b.z);
}
我正在选择尺寸更大的类型:
帮助器模板:
template<bool b, typename A, typename B>
struct choose_if
{
typedef A type;
};
template<typename A, typename B>
struct choose_if<false, A, B>
{
typedef B type;
};
template<typename A, typename B>
struct greater
{
static const bool value = sizeof(A) > sizeof(B);
typedef vector<typename choose_if<value, A, B>::type> type;
};
模板
结构选择\u如果
{
类型定义类型;
};
模板
结构选择\u如果
{
B型;
};
模板
大结构
{
静态常数布尔值=sizeof(A)>sizeof(B);
类型定义向量类型;
};
现在使用它:
template <typename A, typename B>
typename greater<A, B>::type operator +(const vector<A> &a, const vector<B> &b)
{
typedef typename greater<A, B>::type type;
return type(a.x+b.x, a.y+b.y, a.z+b.z);
}
模板
typename greater模板在编译时是专门化的,没有任何理由编译器不能创建一个重载来接受向量
和向量
,并返回一个向量
。诀窍是让它做到这一点,而不为每个组合重复源代码。这种方法很有效,我已经完成了以前也用过类似的东西。你需要更多的模板胶,采用两种类型并比较它们的精度水平,以便进行“条件”类型定义,但这是非常可行的。诀窍是先进行减法,然后进行部分专业化。嗯,问题是我知道如何进行部分专业化