通用类的每个实例化都会增加编译时变量

Vik*_*ehr 5 c++ generic-programming c++11

我有这门课:

template <typename T, uint64_t N>
struct Probe {
  static const uint64_t Counter = N;
  typedef T Type;
};
Run Code Online (Sandbox Code Playgroud)

我用它作为:

typedef Probe <int, 0> FirstIntProbe;
typedef Probe <int, 1> SecondIntProbe;
typedef Probe <float, 2> FloatProbe;
Run Code Online (Sandbox Code Playgroud)

是否可以创建一个编译时\宏方法,它允许我实例化此类而不指定第二个参数,例如:

typedef Probe <int, Something?> FirstIntProbe;
typedef Probe <int, Something?> SecondIntProbe;
typedef Probe <float, Something?> FloatProbe;
Run Code Online (Sandbox Code Playgroud)

我认为这是不可能的,但我再次看到人们用C++做事我以前认为不可能.


更新:

  • 没有必要增加一个,每个探针都有它自己的数字是很重要的.
  • 不需要在不同的.cpp文件\翻译单元中具有唯一编号.

she*_*heu 7

您可以查看使用__COUNTER__宏,它是一个编译器扩展(但在GCCMSVC等支持).请注意,__COUNTER__每个翻译单元是唯一的,即每个.cpp文件.

编辑:在多个翻译单元中包含标题即可.此示例链接并运行完全正常(基于GCC 4.5构建):

probe.h:

template <typename T, int N>
struct Probe {
    typedef T Type;
};

#define DECLARE_PROBE(type) typedef struct Probe<type, __COUNTER__>
Run Code Online (Sandbox Code Playgroud)

main.cpp:

#include "test.h"

DECLARE_PROBE(int) intprobe;
DECLARE_PROBE(float) floatprobe;

int main(int argc, char** argv) {
    intprobe ip;
    floatprobe fp;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

test.cpp:

#include "test.h"

DECLARE_PROBE(int) intprobe;
DECLARE_PROBE(float) floatprobe;

static intprobe ip;
static floatprobe fp;
Run Code Online (Sandbox Code Playgroud)

  • 这怎么办?每个翻译单元的每次使用都会扩展`__COUNTER__`.因此,如果`Probe`位于标题中,并且包含在多个转换单元中,则由于违反了一个定义规则,您将具有未定义的行为,即使`Probe`仅存在于单个转换单元中,如果`__COUNTER__`是宏的一部分,它只会扩展一次. (2认同)

Jam*_*nze 5

如果你不需要一个整数常量表达式(即你不是Counter用作数组的维数等),它实际上非常简单:只需对计数器使用全局静态(或者将它放在非模板化的基类中) ),并在每次在初始化中使用它时递增它.就像是:

int currentProbeCounter;

template <typename T>
struct Probe
{
    static int const counter;
    //  ...
};

template <typename T>
const int Probe<T>::counter = ++ currentProbeCounter;
Run Code Online (Sandbox Code Playgroud)

请注意,这只会Probe<T>::counter在您使用它时(或者如果)分配给定类型; 您可能希望在Probe(即使您不需要)的构造函数中使用它来确保其创建.(另一方面,如果你从不使用它,谁会关心它是否从未被创造过.)