我正在处理运算符重载以生成惰性对象评估。出于这个原因,operator +()的类不仅仅是存储传递类的引用以便稍后进行求值。
struct Base
{
virtual void expensive_func()
{
throw "cant use this";
};
Composer operator+(int i)
{
return Composer(*this, i);
}
}
struct Composer:public Base
{
Base& refBase;
int increment;
virtual void expensive_func()
{
heavy_work();
};
Composer(Base& a,int inc):
refBase(a),increment(inc)
{
}
}
struct D:public Base
{
...
}
而不是问题arase
D a;
auto b = a + 2;
auto c = b + 3;
auto e = a + 3 + 4;
a.expensive_func(); //fine
b.expensive_func(); //fine
c.expensive_func(); //fine
e.expensive_func(); //segfault
解决方案是用
防止这种演习operator+(const Coposer&&,int) = delete;
但这只是阻止做我想做的事情
完整代码: - 我正在使用gcc / g ++ 4.8构建
#include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>
#include <memory>
namespace Intervals
{
template <typename T> struct ContainerMove; //forward declaration
template <typename T>
struct ContainerBase {
typedef T mT;
virtual T GetInterval (const T& val)
{
throw; //overload this
}
T Integrate(const T& start = T(0))
{
T r(0);
T next(start);
while(1)
{
T i = GetInterval(next);
if(i<0) //less that 0 is considered end
{
return r;
}
r+=i;
next=i;
}
}
ContainerMove<T> operator +(const T& left);
ContainerMove<T> operator -(const T& left);
virtual ~ContainerBase(){};
};
//lazy container of ContainerBase
template <typename T>
struct ContainerMove:public ContainerBase<T>
{
typedef ContainerBase<T> mConatinerBase;
const T mOffset;
mConatinerBase& mIntervalSet;
ContainerMove(mConatinerBase& intervalset, const T& offset)
:mOffset(offset),mIntervalSet(intervalset)
{}
virtual T GetInterval (const T& val)
{
auto i = mIntervalSet.GetInterval(val-mOffset);
if(i < 0)
{
return T(-1000);
}
return T(i+mOffset);
}
};
template <typename T>
ContainerMove<T> ContainerBase<T>::operator +(const ContainerBase<T>::mT& a)
{
return ContainerMove<T>(*this,a);
}
template <typename T>
ContainerMove<T> ContainerBase<T>::operator -(const ContainerBase<T>::mT& a)
{
return ContainerMove<T>(*this,-a);
}
/*
template <typename T>
ContainerMove<T> operator +(const ContainerMove<T>&& , const typename ContainerBase<T>::mT&) = delete;
template <typename T>
ContainerMove<T> operator -(const ContainerMove<T>&& , const typename ContainerBase<T>::mT&) = delete;
*/
template <class T>
struct Container:public ContainerBase<T>
{
typedef Container<T> mThisType;
typedef T mT;
typedef std::vector<T> SortedContainer_t;
SortedContainer_t mContainer;
template<class ForwardIter>
Container(ForwardIter begin,ForwardIter end)
:mContainer(begin,end)
{
}
T GetInterval (const T& val)
{
auto r = std::upper_bound(mContainer.begin(), mContainer.end(),val);
if (r == mContainer.end())
{
return T(-1000); //just as exeample <0 is ivalid value
}
return *r;
}
};
}
int main()
{
typedef float T;
typedef Intervals::Container<T> ContainerType;
std::vector<T> v,u;
const int N = 10;
for(int i=0;i<N;++i)
{
v.push_back(T(i));
}
auto c = ContainerType(v.begin(),v.end());
auto d=c+T(1);
auto e=c+T(2)+T(3); //this yelds segmentation after e.Integrate()
//std::cout << c.Integrate() << std::endl;
//std::cout << d.Integrate() << std::endl;
std::cout << e.Integrate() << std::endl; //crash here
return 0;
}