实例彼此独立的唯一类型的计数器

Jaa*_*aan 1 c++

我试图为计数器接收到的每个唯一模板参数创建一个计数器。

例如,我传递一个 int。计数器返回零。我经过一个花车。计数器返回 1。我再次传递一个 int 。计数器返回零。本质上,它为每个模板化类型生成一个唯一的整数。

struct Counter {
    template<typename T>
    int type();
    int tick();
};

template<typename T>
int Counter::type() {
    static int index = tick();
    return index;
}

int Counter::tick() {
    static int index = 0;
    return index++;
}

int main() {
    Counter countera;
    Counter counterb;

    std::cout << countera.type<int>() << std::endl;
    std::cout << countera.type<float>() << std::endl;
    std::cout << countera.type<double>() << std::endl;

    std::cout << counterb.type<float>() << std::endl;
    std::cout << counterb.type<int>() << std::endl;
    std::cout << counterb.type<double>() << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面我们看到了这个计数器的一个例子。然而,有一个问题。如果我声明计数器的两个实例,则下一个计数器会记住前一个计数器的顺序。例如,上面的代码打印顺序 0 1 2 1 0 2。我理想的计数器会打印 0 1 2 0 1 2。我没有在这里解释原因,但就我的目的而言,这是一个问题。这里的解决方案似乎是更多的模板。

template<typename T, int Version>
int Counter<V>::type() {
    static int index = tick();
    return index;
}
Run Code Online (Sandbox Code Playgroud)

与之前的代码非常相似,但是还有另一个模板。现在,我可以像下面这样声明我的计数器。

Counter<0> countera;
Counter<1> counterb;
Run Code Online (Sandbox Code Playgroud)

此解决方案有效,但我不想为计数器的每个实例手动输入每个数字。我尝试了以下方法。

constexpr inline int tick() {
    static inline int i = 0;
    return i++;
}

template<typename T, int Version = tick()>
int Counter<V>::type() {
    static int index = tick();
    return index;
}
Run Code Online (Sandbox Code Playgroud)

然而,这不起作用,因为我在 constexpr 函数内有一个非 constexpr 变量。有谁知道这个问题的解决方案?也许有一个例子可以说明我如何以另一种方式解决这个问题?

谢谢

注意:我这样做是出于性能原因。这会经常被调用,我想避免使用地图。

另一个注意事项:整数必须是连续的。它们将用作双端队列的索引。因此,任何 typeid() 的东西都不起作用。

Bri*_*ian 5

您希望在编译时计算计数器值,其中不同的实例具有Counter单独的计数器。这里的主要障碍是,无法始终在编译时确定您正在使用的计数器实例是否与已使用的其他计数器实例相同。换句话说,当您执行 时counter.type<T>(),结果取决于所引用的Counter对象的当前计数器值。counter但其本身:该对象的身份Counter:在编译时可能不知道。例如:

Counter countera;
Counter counterb;
countera.type<int>();
std::cin >> x;
std::cout << (x ? countera : counterb).type<double>();
Run Code Online (Sandbox Code Playgroud)

最后一行强制在运行时检查Counter三元表达式计算结果的实例的当前计数器值,以确定是否返回10

为了解决这个问题,您可以指定要使用哪个计数器实例,以保证在编译时修复的方式:

struct Counter {};

template <Counter& counter>
int tick() {
    static int index = 0;
    return index++;
}

template <Counter& counter, typename T>
int type() {
    static int index = tick<counter>();
    return index;
}

int main() {
    static Counter countera;
    static Counter counterb;

    std::cout << type<countera, int>() << std::endl;
    std::cout << type<countera, float>() << std::endl;
    std::cout << type<countera, double>() << std::endl;

    std::cout << type<counterb, float>() << std::endl;
    std::cout << type<counterb, int>() << std::endl;
    std::cout << type<counterb, double>() << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这给出了您想要的输出。神箭