是否有等价的#if可以评估模板参数?

dar*_*ius 3 c++ macros templates

所述#if预处理指令评估已知的预处理器"的常数"的表达.是否有类似的东西可以评估模板参数的表达式?

在实践中,我有这样的事情:

template<int i>    
class Elem{ /*...*/};

#ifndef NUM_ELEM
#define NUM_ELEM 2 
#endif    

class MyClass
{

    #if NUM_ELEM >= 1
        Elem<1> e_1;
    #endif
    #if NUM_ELEM >= 2
        Elem<2> e_2;
    #endif
    #if NUM_ELEM >= 3
        Elem<3> e_3;
    #endif

    /*...*/
}
Run Code Online (Sandbox Code Playgroud)

但我真的想让MyClass成为一个模板:

template<int num_elem>
MyClass{

    #if num_elem >= 1 //but #if can't understand num_elem
        Elem<1> e_1;
    #endif
    #if num_elem >= 2
        Elem<2> e_2;
    #endif
    #if num_elem >= 3
        Elem<3> e_3;
    #endif 

    /*...*/
};
Run Code Online (Sandbox Code Playgroud)

dav*_*mac 7

简短的回答是否定的,但如果你愿意稍微改变一下你的要求,你可以这样做:

// A run of elements - Elem<n>, ..., Elem<2>, Elem<1>
template <int n> class NumElems
{
    template <int u, int v> friend class ElemGetter;

    NumElems<n-1> before;

    public:
    Elem<n> e;

    // method to retrieve an element by number
    template <int m> Elem<m> &getElem();
};

// helper class to retrieve an element.
//  'n' is the element number to retrieve
//  'm' is the number of elements
// by default, ElemGetter<n,m> defers to ElemGetter<n,m-1>.
template <int n, int m> class ElemGetter
{
    public:
    static Elem<n> &getElem(NumElems<m> &numElems)
    {
        return ElemGetter<n,m-1>::getElem(numElems.before);
    }
};

// specialisation of ElemGetter: if the element to get is the same as the
// number of elements (i.e. is the last element) then return it
// immediately.
template <int n> class ElemGetter<n,n>
{
    public:
    static Elem<n> &getElem(NumElems<n> &numElems)
    {
        return numElems.e;
    }
};

// get an element by number; defers to the ElemGetter helper.
template <int n> template <int m> Elem<m> &NumElems<n>::getElem()
{
    return ElemGetter<m,n>::getElem(*this);
}

template <> class NumElems<0>
{
};
Run Code Online (Sandbox Code Playgroud)

...然后您可以声明您的Elem成员集:

NumElems<NUM_ELEM> elems;
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方式访问它们:

Elem<2> &e = elems.getElem<2>();
Run Code Online (Sandbox Code Playgroud)

原始提议的代码

我提出的原始代码实际上并没有编译,但我会在这里包含它,因为它更好地展示了上述的意图:

// Original, doesn't compile - but it would be nice if it did :/
template <int n> class NumElems : private NumElems<n-1>
{
    Elem<n> e;

    template <int m> Elem<m> &getElem()
    {
        return NumElems<n-1>::getElem<m>();
    }

    template <> Elem<n> &getElem<n>()
    {
        return e;
    }
};

template <> class NumElems<0>
{
};
Run Code Online (Sandbox Code Playgroud)

遗憾的是,C++不允许以这种方式对成员模板函数进行专门化,虽然它(我)为什么不明白 - 代码肯定更简单,无需创建辅助类,如上面的工作代码.

  • 私有继承可能是一个很好的例子,除非你认为`NumElems <3>`是一个`NumElems <2> (2认同)