c++ - 非类型模板参数不是常量表达式

标签 c++ templates c++11 constexpr clang++

我有以下代码:

#include <cstdlib>
#include <cstdio>
#include <atomic>

enum ATYPE { Undefined = 0, typeA, typeB, typeC };

template<ATYPE TYPE = Undefined>
struct Object
{
    Object() { counter++; }
    static std::atomic<int> counter;
};

template<ATYPE TYPE>
std::atomic<int> Object<TYPE>::counter(1);

template<ATYPE TYPE>
void test()
{
    printf("in test\n");
    Object<TYPE> o;
}

int main(int argc, char **argv)
{
    test<typeA>();
    printf("%d\n", Object<typeA>::counter.load());
    Object<typeA>::counter.store(0);
    for (int i = 0; i < sizeof(ATYPE); ++i) {
        Object<static_cast<ATYPE>(i)>::counter.store(0);
    }
    return 0;
}

当我使用以下命令行编译时:

clang++ -o test -std=c++11 -stdlib=libc++ test.cpp

我收到以下错误:

test.cpp:32:20: error: non-type template argument is not a constant expression
Object<static_cast<ATYPE>(i)>::counter.store(0);
^~~~~~~~~~~~~~~~~~~~~
test.cpp:32:39: note: read of non-const variable 'i' is not allowed in a constant expression
Object<static_cast<ATYPE>(i)>::counter.store(0);
^
testray.cpp:31:18: note: declared here
for (int i = 0; i < sizeof(ATYPE); ++i) {

我理解我相信的问题。模板的参数需要是一个 constexpr 而 i 显然不是。所以问题是,他们是否可以做一些改变来使它正常工作。通过这种工作,我的意思是,除了手动操作之外,我能否以某种方式从该模板类中为 ATYPE 中的每种类型重置这些静态计数器:

Object<Undefined>::counter.store(0);
Object<typeA>::counter.store(0);
...

当ATYPE包含很多类型时,就显得不那么优雅和实用了。

非常感谢您的帮助和建议。

最佳答案

对于这类事情,递归通常是一个简单的解决方案:

#include <type_traits>

enum ATYPE { Undefined = 0, typeA, typeB, typeC, ATYPE_END };

void reset_Object_counter(std::integral_constant<ATYPE, ATYPE_END>)
{}

template < ATYPE n = Undefined >
void reset_Object_counter(std::integral_constant<ATYPE, n> p = {})
{
    Object<p>::counter.store(0);
    reset_Object_counter(std::integral_constant<ATYPE,
                                                static_cast<ATYPE>(n+1)>{});
}

对于这种情况,据我所知,函数模板特化也有效(而不是第一次重载):

template<>
void reset_Object_counter<ENUM_END>(std::integral_constant<ATYPE, ENUM_END>)
{}

无论哪种方式,用法都是 reset_Object_counter();设置所有 Object<...>的柜台 0 .


integral_constant这里的解决方案实际上有点矫枉过正,对于这个问题一个非类型模板参数就足够了(因为函数模板特化可以代替结束递归的重载)。

template < ATYPE n = Undefined >
void reset_Object_counter()
{
    Object<n>::counter.store(0);
    reset_Object_counter<static_cast<ATYPE>(n+1)>();
}
template<>
void reset_Object_counter<ENUM_END>()
{}

关于c++ - 非类型模板参数不是常量表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18177721/

相关文章:

c++ - 关于容器中元素的引用

c++ - 在 C++ 中,如何在没有动态分配(即 NEW)的情况下将对象初始化为对象内部的指针?

c++ - 第一个模板中的 "::type=0"是什么意思?

c++ - 对模板函数的引用 vector

c++ - 使用多个线程的并行 vector 乘法比顺序 vector 乘法花费更长的时间

c++ - 在 Qt 中为 QTableView 创建弹出菜单

c++ - std::streambuf::overflow 的正确实现

C++ 不同类型模板化类的显式模板化函数实例化

c++ - 具有 'const' 参数重载的可变参数模板

c++ - 在 C++ 中嵌套的 unordered_maps