简体   繁体   English

模板元编程或操作

[英]template meta-programming OR operation

I have a class that can be decorated with a set of add-on templates to provide additional functionality. 我有一个可以用一组附加模板装饰的类,以提供其他功能。 Each add-on has an identifying addon_value that the base class needs to know. 每个附加组件都有一个基类需要知道的标识addon_value。

The code below is an example of what I would like to do. 下面的代码是我想做的一个例子。 Obviously, the main() function fails to compile. 显然,main()函数无法编译。 The goal is for CBase::GetValueOfAddOns() to know the value of OR-ing the addon_value for each add-on. 目标是让CBase :: GetValueOfAddOns()知道对每个附加组件的addon_value进行或运算的值。 The calculation does not actually have to be performed in GetValueOfAddOns(), it just has to be able to get at the result. 该计算实际上不必在GetValueOfAddOns()中执行,它只需要能够得出结果即可。

template< class T >
class AddOn_A : public T
{
public: 
    AddOn_A( int x ) : T( x ) 
    {};

    enum { addon_value = 0x00000001 };
};

template< class T >
class AddOn_B : public T
{
public: 
    AddOn_B( int x ) : T( x ) 
    {};

    enum { addon_value = 0x00000010 };
};

class CBase
{
public:
    explicit CBase( int x ) : x_( x ) 
    {
        // error LNK2001: unresolved external symbol "public: virtual int __thiscall CBase::GetValueOfAddOns(void)const " (?GetValueOfAddOns@CBase@@UBEHXZ)
        int z = GetValueOfAddOns();
    };

    virtual int GetValueOfAddOns() const = 0;

private:
    int x_;
};

// define an empty AddOn
template< class > class empty 
{
public:
    enum { addon_value = 0x00000000 };
};

// forward declaration and Add-On defaults
template< template< class > class AddOn1 = empty,
          template< class > class AddOn2 = empty,
          template< class > class AddOn3 = empty >
class CMyClass;

// specialized template for the default case
template<> class CMyClass< empty, empty, empty > : public CBase
{
public:
    CMyClass( int x ) : CBase( x ) 
    {};

    enum { addon_value = 0x00000000 };
};

// actual definition
template< template< class > class AddOn1,
          template< class > class AddOn2,
          template< class > class AddOn3 >
class CMyClass : public AddOn1< CBase >,
                 public CMyClass< AddOn2, AddOn3 >
{
public:
    CMyClass( int x ) : AddOn1< CBase >( x ),
                        CMyClass< AddOn2, AddOn3 >( x )
    {};

    enum { addon_value = AddOn1< CBase >::addon_value | CMyClass< AddOn2, AddOn3 >::addon_value };

    int GetValueOfAddOns() const
    {
        return addon_value;
    }
};

int _tmain( int argc, _TCHAR* argv[] )
{
    CMyClass< AddOn_A > A( 0 );
    _ASSERT( A.GetValueOfAddOns() == AddOn_A< CBase >::addon_value );

    CMyClass< AddOn_A, AddOn_B > AB( 0 );
    _ASSERT( AB.GetValueOfAddOns() == ( AddOn_A< CBase >::addon_value | AddOn_B< CBase >::addon_value ) );

    return 0;
}

Thanks for any help, PaulH 感谢您的帮助,PaulH

Not sure this is the most elegant way, but the following is fairly straightforward: 不确定这是最优雅的方法,但是以下内容非常简单:

Add this to CMyClass: 将此添加到CMyClass:

enum {AddonsValues = AddOn1<CBase>::addon_value | CMyClass<AddOn2, AddOn3>::AddonsValues};

int GetValueOfAddOns()
{
    // return the result of OR-ing the addon_value of each add-on.
    return AddonsValues;
};

and this to the specialized CMyClass<empty, empty, empty> : 这是专门的CMyClass<empty, empty, empty>

enum {AddonsValues = 0};

If you make that function pure virtual , you can implement it in CMyClass , where you have all information available. 如果使该函数成为纯virtual函数,则可以在CMyClass实现它,在该函数中您可以获得所有可用信息。 Just change your empty class to define enum { addon_value = 0x00000000 }; 只需更改您的empty类以定义enum { addon_value = 0x00000000 }; , which will make this easier. ,这将使此操作更加容易。

Let's make it better: 让我们做得更好:

See your new question about the problem with hierarchy here I have solved the AddOnValues problem there as well, and there is no need for template meta-programming, really. 在这里看到有关层次结构问题的问题,我也在那里解决了AddOnValues问题,实际上,不需要模板元编程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM