2013-08-11 27 views
5

Tôi có đoạn mã sau:Non-kiểu mẫu lập luận không phải là một biểu thức hằng

#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; 
} 

Khi tôi biên dịch với các dòng lệnh sau:

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

tôi nhận được các lỗi sau đây:

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

Tôi hiểu vấn đề tôi tin. Đối số của mẫu cần phải là một constexpr và tôi rõ ràng là không. Vì vậy, câu hỏi là, họ có thể thay đổi tôi có thể làm để có được điều này làm việc. Bằng cách làm việc này, ý tôi là, tôi có thể bằng cách nào đó có một cách tốt hơn để thiết lập lại các quầy tĩnh từ mẫu này lớp đối với từng loại trong ATYPE, khác hơn là chỉ làm nó bằng tay:

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

Mà không phải là quá thanh lịch và thiết thực khi ATYPE chứa nhiều loại.

Cảm ơn rất nhiều sự giúp đỡ và lời khuyên của bạn.

+1

Bạn đang lặp lại lỗi enum của mình. 'i' không phải là một biểu thức liên tục hoặc là lỗi hiển thị. – Rapptz

+0

@Rapptz, bạn có thể vui lòng cụ thể hơn về bình luận đầu tiên của bạn (lặp lại thông qua enum sai). Tôi biết tôi không phải là const, vì vậy đó là lý do tại sao tôi hỏi nếu bằng cách nào đó là một cách để làm công việc này. Có cách nào đó một cách lặp lại trên tất cả các yếu tố của enum và đặt lại các quầy? cảm ơn bạn. – user18490

+0

Điều Rapptz có nghĩa là tôi năng động và không thể được sử dụng như một đối số mẫu biên dịch thời gian –

Trả lời

7

Đối với những loại của sự vật, đệ quy thường là một giải pháp đơn giản:

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

Đối với trường hợp này, AFAIK, chức năng mẫu chuyên môn làm việc cũng như (thay vì quá tải đầu tiên):

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

Dù bằng cách nào, việc sử dụng chỉ là reset_Object_counter(); để đặt tất cả các quầy của Object<...> thành 0.


Giải pháp integral_constant thực sự là một chút quá mức cần thiết ở đây, đối với vấn đề này một mẫu tham số không kiểu là đủ (vì chức năng mẫu chuyên môn có thể chiếm chỗ của sự quá tải kết thúc đệ quy).

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

Tuyệt vời. Đó là nơi tôi nhận ra tôi không biết C++ đủ. Tôi chưa bao giờ nghe nói về integ_constant ... nhưng tôi bắt kịp tất cả những điều mới chúng ta có thể tìm thấy trong C++ 11 và có vẻ như nó có thể mất cả đời. Cảm ơn rất nhiều câu trả lời và thx cho mọi người khác. – user18490

+0

@ user18490 'Integrity_constant' thậm chí không cần thiết ở đây;) – dyp

+0

vâng tôi thực sự đang cố gắng viết mã mà không có, bởi vì tôi đoán nó có thể làm việc mà không có, nhưng tôi vui mừng khi học điều gì đó. Cảm ơn nhận xét bổ sung này. – user18490

Các vấn đề liên quan