如何在C ++中的编译时设计带有可切换成员变量的模板类? [英] How to design a template class with switchable member variables at compile-time in C++?

查看:50
本文介绍了如何在C ++中的编译时设计带有可切换成员变量的模板类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

|■探针定义____________________

我正在尝试设计一个满足以下属性的超灵活但内存高效的模块.

I'm trying to design a super-flexible, but memory efficient module satisfying below properties.

  1. 它可以根据情况关闭不必要的成员变量.
  2. 将拥有哪些变量在编译时确定.

我以某种方式使用枚举器标志确定了其成员列表" 之前 /strong>.见下文:

I somehow made one which determines its member list "before" the compile-time, using macros and enumerator flags. see below :

▼TraitSwitch.h

#pragma once
// Macros to switch-off source codes themselves.
#define ON                 1
#define OFF                0

#define TRI_AREA_INFO      ON
#define TRI_CENTROID_INFO  ON
#define TRI_NORMAL_INFO    OFF // When the normal vector info is unnecessary.
...

▼TriangleTraits.h

#pragma once
#include <cstdint>
#include "TraitSwitch.h"

enum TriangleTrait : uint8_t
{
    NONE          = 0,   // 0000 0000

#if (TRI_AREA_INFO == ON)
    AREA          = 1,   // 0000 0001
#endif

#if (TRI_CENTROID_INFO == ON)
    CENTROID      = 2,   // 0000 0010
#endif

#if (TRI_NORMAL_INFO == ON) //        | Inactive Preprocessor Block
    NORMAL_VECTOR = 4,   // 0000 0100 |
#endif
    ... // more traits

    ALL           = 255  // 1111 1111
}
// Need some additional overloaded bitwise-operators (&, |, |=, etc ...)

▼Triangle.h

#pragma once
#include "TriangleTraits.h"

class Triangle
{
public:
    Triangle() {}
    ~Triangle() {}

#if (TRI_AREA_INFO == ON)
    double area;
#endif

#if (TRI_CENTROID_INFO == ON)
    double centroid[3]; // x, y, z
#endif

#if (TRI_NORMAL_INFO == ON) //   | Inactive Preprocessor Block
    double normal[3]; // x, y, z |
#endif
    ...

    TriangleTrait alreadyComputed; // To avoid redundant works.
    void ComputeTraits(TriangleTrait _requested)
    {
        if (((_requested & TriangleTrait::AREA) != 0) 
            && ((alreadyComputed & _requested) == 0))
        {
            this->ComputeArea();
            alreadyComputed |= TriangleTrait::AREA;
        }
        ... // do the same things for centroid, normal
    }

private:
    void ComputeArea();
    void ComputeCentroid();
    void ComputeNormal();
    ...
}

然后,对象上的 C ++ IntelliSense 可能显示:

then, C++ IntelliSense on the object may show : this

▼main.cpp

#include <iostream>
#include "Triangle.h"

int main(void)
{
    Triangle tri;
    tri.ComputeTraits(TriangleTrait::AREA | TriangleTrait::CENTROID);

    std::cout << "area : " << tri.area << "m²" << std::endl;
    std::cout << "centroid : (" 
        << tri.centroid[0] << "," 
        << tri.centroid[1] << "," 
        << tri.centroid[2] << ")" << std::endl;
    ...
}

首先 Triangle.h 看起来很丑陋,即使看起来不错,该方法也会确定类成员" before" 无论如何,编译时间.

Firstly Triangle.h looks quite ugly, and even if it looks good, this method determines class members "before" the compile-time, anyway.


|■问题摘要____________________

如何设计具有可切换成员的模板类,该成员在编译时确定."

"How to design a template class with switchable members, which are determined at the compile-time."

这就是我想要的东西:

▼main.cpp

...

int main(void)
{
    Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA)> tri1; // This owns area info only
    tri1.area;

    Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA | CENTROID)> tri2; // This owns area & centroid info
    tri2.area;
    tri2.centroid;

    Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA | NORMAL)> tri3; // This owns area & normal vector info
    tri3.area;
    tri3.normal;
    ...

    Triangle<__MACRO_DEFINED_TRAIT_SWITCH(AREA | CENTROID | NORMAL)> tri4; // This owns area & centroid & normal vector info
    tri4.area;
    tri4.centroid;
    tri4.normal;
    ...
}

我猜想结合使用模板和宏(可能使用 Tag-dispatching 方法?)可以完全实现我想要的功能,但是没有任何明确的想法.

I guess using templates combined with macros (with Tag-dispatching method, maybe?) will do exactly what I want, but have no any clear idea.

推荐答案

经过几天的困扰,我找到了一种方法.所以我自己回答我的问题.

After a few days of distress, I found a way. So I'll answer my question myself.

灵魂很简单.只需将多个继承与可变参数模板一起使用.见下文:

The soultion was tooooo simple. Just use multiple inheritances with variadic templates. See below:

▼TriangleTraits.h

struct AREA
{
    double area;
};

struct CENTROID
{
    double centroid[3];
};

struct NORMAL
{
    double normal[3];
};
... // more traits

// Multiple Inheritances with variadic template
template<class... Traits>
struct TriangleWithTraits : Traits... 
{
};

▼main.cpp

#include "TriangleTraits.h" // Just include this one is enough

int main()
{
    TriangleWithTraits<AREA> tri1;
    tri1.area;

    TriangleWithTraits<AREA, CENTROID> tri2;
    tri2.area;
    tri2.centroid;

    TriangleWithTraits<AREA, NORMAL> tri3;
    tri3.area;
    tri3.normal;

    TriangleWithTraits<AREA, CENTROID, NORMAL> tri4;
    tri4.area;
    tri4.normal;
    tri4.centroid;
...
}

这篇关于如何在C ++中的编译时设计带有可切换成员变量的模板类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆