2013-08-11 5 views
5

ではありません。非型テンプレート引数には、私は次のコードを持っている定数式

#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である必要があり、明らかにそうではありません。だから、問題は、私はこれを実現するために可能な変更が可能なのかどうかということです。

とてもエレガントで実用的ではない
Object<Undefined>::counter.store(0); 
Object<typeA>::counter.store(0); 
... 

:この作業では、私が意味する、私は何とかちょうどそれを手動で行うよりも、他のATYPEの各タイプについて、このテンプレートクラスからこれらの静的カウンタをリセットするより良い方法を持つことができますATYPEには多くの種類があります。

ご協力いただきありがとうございます。こんなもののために

+1

とにかくあなたの列挙型を間違ってループしています。 'i'はエラーが示すように定数式ではありません。 – Rapptz

+0

@Rapptz、最初のコメント(enumを間違って繰り返している)について詳しく説明してください。私は私がconstではないことを知っています。だから、どういうわけかこの仕事をする方法があるのか​​どうか尋ねているのです。列挙型のすべての要素をループしてカウンターをリセットする方法は何とかありますか?ありがとうございました。 – user18490

+0

Rapptzとは、私が動的であり、コンパイル時のテンプレート引数として使用できないということです。 –

答えて

7

は、再帰は通常、シンプルなソリューションです。このケースでは

#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>) 
{} 

どちらの方法でも、Object<...>のカウンタをすべて0に設定すると、使用方法はreset_Object_counter();になります。 (関数テンプレートの特殊化は、再帰を終了過負荷の場所を取ることができるので)


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>() 
{} 
+0

すばらしい。それで、私はC++を十分に知らないことに気がつきます。私はintegral_constantについて聞いたことがありません...しかし私はC++ 11で見つけることができるすべての新しいものに追いついており、それは生涯かかるかもしれないようです。おかげで多くの偉大な答え、そして他のみんなにthx。 – user18490

+0

@ user18490 'integral_constant'はここでも必要ではありません;) – dyp

+0

はい私は実際にコードを書きませんが、私はそれがなくても動作すると思っていたので、とにかく何かを覚えていました。この追加発言をありがとう。 – user18490

関連する問題