具有常量和变量变化的C ++模板

时间:2014-07-01 16:35:58

标签: c++ templates

我想制作一个模板,支持使用编译时常量或可在运行时更改的动态变量的变体,以支持每个代码路径的最佳变化。

一个简单的例子是这样的,一个小的类,它将一个数字递增到一个定义的饱和点:

template< typename T, T aSatValue >
class cIncrementor
{
public:
    typedef cIncrementor< T, aSatValue >    tIncrementor;

    cIncrementor( T aValue ) { mValue = aValue; }

    tIncrementor & operator++ ( int )
    {
        if( mValue >= aSatValue )
        {
            mValue = aSatValue;
        }
        else
        {
            mValue++;
        }
        return( *this );
    }

    T mValue;
};

(这个类的功能并不重要,我试图解决的关键是支持常量和可变数据的好模式)。

在此版本中,饱和度值是在运行时定义的常量,您可以使用此模板:

    cIncrementor<int,32> lIncer(0); // maximum value of 32 and start at 0
    lIncer++; // test incrementing

我希望有一个类的可选变体,它可以在运行时动态提供饱和度值,但是我不希望在类中存储额外值以用于常量情况,我不想复制代码。

构建这样的模板的最佳方法是什么,以便它们可以使用常量值或变量?

谢谢!

2 个答案:

答案 0 :(得分:3)

没有&#34;最佳实践&#34;我知道这样做的方式。但是,模板可用于完成几乎任何事情。 这个解决方案有点复杂,但是你问了......

template< typename T, T SatValue >
class ConstSatValue
{
public:
    ConstSatValue(T) { }  //ignore the parameter as its irrelevant

    constexpr T getSatValue()
    { return SatValue; }
};

template< typename T >
class DynamicSatValue
{
public:
    DynamicSatValue(T sat)
    : satValue(sat) { }

    T getSatValue()
    { return satValue; }

private:
    T satValue;
};

template< typename T, typename aSatValue >
class cIncrementor: private aSatValue
{
public:
    typedef cIncrementor< T, aSatValue >    tIncrementor;

    cIncrementor( T aValue, T satValue = 0 )
    : aSatValue(satValue), mValue(aValue) { }

    tIncrementor & operator++ ( int )
    {
        T satValue = getSatValue(); //assumed present in base class
        if( mValue >= satValue )
        {
            mValue = satValue;
        }
        else
        {
            mValue++;
        }
        return( *this );
    }

    T mValue;
};

你这样使用它:

cIncrementor<int, ConstSatValue<int, 32>> constBounded(0);
int bound = 32;
cIncrementor<int, DynamicSatValue<int>> dynamicBounded(0, bound);

这取决于空基类优化和constexpr以获得所需的行为。它为编译器提供了在编译时常量情况下不存储饱和点所需的所有信息,同时仍为动态绑定提供了接口。

但是,我仍然会强烈考虑这种额外的复杂性是否值得您节省的极少量内存。

答案 1 :(得分:2)

答案

无法满足您的所有要求:

  • 没有代码重复
  • 班上没有额外的物品
  • 动态饱和度值

这根本不可能,因为要提供运行时对象,您需要一个用于存储此运行时值的对象。

我要做什么

如果您的饱和度值需要保持不变并且可以在运行时提供,那么您最好的选择是在类中有一个额外的const对象:

template< typename T >
struct cIncrementor
{

    cIncrementor( const T& aValue, const T& bValue) 
        : mValue(aValue)
        , sValue(bValue)
        {}

    cIncrementor & operator++ ( int )
    {
        if( mValue >= sValue )
        {
            mValue = sValue;
        }
        else
        {
            mValue++;
        }
        return( *this );
    }

    T mValue;
    const T sValue;

};

还要记住,编译器优化的方式是无限的。