2013-03-21 50 views
5

Tôi đã tạo một lớp trông giống như một mảng, nhưng thay vì giữ dữ liệu trong chính chương trình, nó truyền byte từ một tệp (để giảm tác động của RAM). Bây giờ tôi đã có tất cả làm việc này, nhưng các lập trình viên phải xác định các lớp sử dụng như sau:Tạo tham số mẫu tại thời gian biên dịch

#define CreateReadOnlyBlock(name, location, size, ...)   \ 
template<>              \ 
const unsigned int ReadOnlyBlock<location, size>::Data[]  \ 
    __asm__(".readonly__" #location "__" #name)    \ 
    = { __VA_ARGS__ };           \ 
ReadOnlyBlock<location, size> name; 

Ví dụ:

//A read only array of {0, 1, 2, 3} 
CreateReadOnlyBlock(readOnlyArray, 0, 4, 0, 1, 2, 3); 

Lưu ý rằng đây là một bộ xử lý nhúng, và chỉ thị asm đi qua một công cụ trong trình biên dịch để tạo tệp chỉ đọc.

Vì vậy, đây là câu hỏi của tôi: làm cách nào tôi có thể loại bỏ các biến "vị trí" và "kích thước"? Tôi ghét rằng các lập trình viên phải gõ những người theo cách thủ công, và rất thích một số cách để tạo ra những người tại thời gian biên dịch. Vì vậy, thay vì các lập trình viên cần phải gõ:

//A read only array at location 0 of {0, 1, 2, 3} 
CreateReadOnlyBlock(readOnlyArray1, 0, 4, 0, 1, 2, 3); 
//A read only array at location 4 of {4, 5, 6, 7} 
CreateReadOnlyBlock(readOnlyArray2, 4, 4, 4, 5, 6, 7); 

Họ chỉ có thể gõ:

CreateReadOnlyBlock(readOnlyArray1, 0, 1, 2, 3); 
CreateReadOnlyBlock(readOnlyArray2, 4, 5, 6, 7); 

Và hằng phù hợp sẽ được tạo ra. Về cơ bản tôi đang tìm kiếm một số cách để tạo và đặt các hằng số này dựa trên các định nghĩa trước đó tại thời gian biên dịch. C++ 11 là trò chơi công bằng, tôi chỉ không quen thuộc với nó (một cái gì đó với constexpr có vẻ hợp lý?). Ngoài ra, C-Preprocessor là okay quá nếu nó không làm cho nó xấu hơn nó đã được. Điều này có thể không?

EDIT cho rõ ràng:

Trong lớp ReadOnlyBlock có phương pháp này:

template<const int _location, const int _size> class ReadOnlyBlock 
    { 
     ... 
     unsigned int operator[] (size_t index) 
     { 
      return LoadFromROM(index + _location); 
     } 
    } 

Có một phụ thuộc lẫn nhau nội tại giữa các biến vị trí và các tập tin ROM mà tôi không thể nghĩ ra làm thế nào để phá vỡ. Tuy nhiên, tôi do cũng có toàn quyền kiểm soát chuỗi công cụ nhưng tôi cần một cách để chuyển công cụ lắp ráp cách xây dựng tệp cũng như chỉ ra mã C++ nơi các khối nằm trong tệp.

Một EDIT:

Các tập tin và các khối của nó có thể khá lớn, càng nhiều càng tốt 1k từ, vì vậy rất nhiều tiền xử lý ma thuật có thể sụp đổ vì rằng. Ngoài ra, cảm ơn tất cả mọi người đã giúp đỡ cho đến nay!

+0

Các '# location' trong phần '__asm__' thực sự đang giết chết nó. Bạn có thực sự cần điều đó hoặc bạn sẽ hài lòng với một giải pháp của phần còn lại chỉ? –

+2

Kích thước rất dễ dàng, nhưng vị trí sẽ yêu cầu ngữ cảnh. Bản mẫu instantiation là một ngôn ngữ chức năng, và kết quả của instantiation chỉ có thể thay đổi dựa trên những gì bạn truyền vào. Nếu bạn chuỗi các khối như vậy, hoặc tạo bộ nhớ trong một mẫu lớn, nó có thể được thực hiện. Tức là, tạo một 'tuple' của mảng chỉ đọc, mỗi mảng có vị trí và kích thước, bắt đầu từ một số vị trí và được đóng gói. – Yakk

+0

Vì vậy, có lẽ tôi nên đưa lý do cho điều đó. Toán tử [] quá tải trong lớp ReadOnlyBlock gọi LoadFromROM (index + location); Công cụ này tạo ra một tệp chỉ đọc có mỗi khối tại mỗi vị trí được chỉ định và lớp biết để tải từ vị trí đó. Tôi không thể nghĩ ra một cách để loại bỏ sự phụ thuộc lẫn nhau, nhưng tôi có toàn quyền kiểm soát công cụ cũng như mã truy cập, vì vậy việc thay đổi nó không nằm ngoài câu hỏi. –

Trả lời

1

tôi vẫn không thấy giải pháp đầy đủ để tạo ra tên (mà #location fragment), nhưng đối với phần còn lại, tôi đoán bạn có thể sử dụng một cái gì đó như này:

template< std::size_t Line > 
struct current_location : current_location< Line - 1 > {}; 

template<> 
struct current_location<0> : std::integral_constant< std::size_t, 0 > {}; 

#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int)) 

#define CreateReadOnlyBlock(name, ...)       \ 
template<>              \ 
const unsigned int ReadOnlyBlock<        \ 
    current_location<__LINE__-1>::value, NUMARGS(__VA_ARGS__) \ 
>::Data[]              \ 
    __asm__(".readonly__" #name)        \ 
    = { __VA_ARGS__ };           \ 
ReadOnlyBlock<current_location<__LINE__-1>::value,    \ 
       NUMARGS(__VA_ARGS__)> name;      \ 
template<>              \ 
struct current_location<__LINE__>        \ 
    : std::integral_constant<std::size_t,      \ 
     current_location<__LINE__-1>::value+NUMARGS(__VA_ARGS__)> \ 
{}; 
+0

Điều này thật hoàn hảo! Cảm ơn bạn rất nhiều. Tôi thực sự không thuyết phục tôi cần #location nữa, vì điều này dường như đưa dữ liệu vào một khối liên tục vững chắc anyways. Tôi là một chút lo lắng rằng trình biên dịch có thể sắp xếp lại thứ mặc dù, đó là nơi tôi sẽ cần định danh vị trí. Trong kịch bản đó, tôi sẽ chỉ đặt vị trí làm chỉ mục đầu tiên trong mảng và lấy công cụ để loại bỏ nó. Không đẹp, nhưng hey nó hoạt động! Một lần nữa, cảm ơn bạn! –

0

Có thể nắm bắt một chút, nhưng nó có thể thực hiện được với các mẫu variadic thay vì va_args không? Một cái gì đó như

template <typename T1, ... TV> 
class ReadOnlyBlock 
{ 
    static unsigned int Data[sizeof(TV) + 1]; 
}; 

về cơ bản, bất cứ nơi nào bạn cần 'vị trí', sử dụng T1. Bất cứ nơi nào bạn cần 'kích thước', sử dụng sizeof (TV) + 1. Không có một trình biên dịch thích hợp để kiểm tra điều này, nhưng có lẽ đó là một cái gì đó để xem xét ...

+0

Nó không thực sự là dữ liệu đang giết tôi ngay bây giờ, nhưng cảm ơn cho đề nghị! Tôi có thể chuyển đổi nó sang các mẫu variadic sau này, tôi chỉ cảm thấy thoải mái hơn với Bộ tiền xử lý C và chỉ cố gắng làm cho nó hoạt động. –

0

Nó có thể hữu ích. Tôi đã viết một số nội dung để đếm các khối có thể thêm DEF_BLOCK(size) cấm khai báo khối.Bạn có thể thử viết lại ví dụ của tôi để phân bổ dữ liệu bên trong các khối của tôi

template<size_t ID> 
struct block_t 
{ 
    enum{location = 0}; 
}; 

#define LAST_BLOCK struct last_block_t{enum{id=__COUNTER__-1};}; 

#define SPEC2(ID, SIZE) template<> struct block_t<ID>{enum{location = block_t<ID-1>::location + SIZE, prev_block = ID-1, size = SIZE};} 
#define SPEC(ID, SIZE) SPEC2(ID, SIZE) 

#define DEF_BLOCK(SIZE) SPEC(__COUNTER__, SIZE) 

DEF_BLOCK(10); 
DEF_BLOCK(11); 
LAST_BLOCK; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::cout << block_t<last_block_t::id>::location << std::endl; 
    return 0; 
} 
0

Nếu sau giữ:

  • Bạn không sử dụng __COUNTER__ elswhere
  • Tất cả các mảng có chiều dài tối đa 5
  • Tất cả các mảng được định nghĩa trong file rất giống

Sau đó, bạn có thể làm điều này:

#include <iostream> 

#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N 
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1) 

template <int... Args> 
struct arg_counter { 
    enum { count = sizeof...(Args) }; 
}; 

#define INC_COUNTER1 arg_counter<-1>::count 
#define INC_COUNTER2 arg_counter<-1, __COUNTER__>::count 
#define INC_COUNTER3 arg_counter<-1, __COUNTER__, __COUNTER__>::count 
#define INC_COUNTER4 arg_counter<-1, __COUNTER__, __COUNTER__, __COUNTER__>::count 
#define INC_COUNTER5 arg_counter<-1, __COUNTER__, __COUNTER__, __COUNTER__, __COUNTER__>::count 

#define INC_COUNTER_IMPL2(count, ...) INC_COUNTER ## count 
#define INC_COUNTER_IMPL(count, ...) INC_COUNTER_IMPL2(count, __VA_ARGS__) 
#define INC_COUNTER(...) INC_COUNTER_IMPL(VA_NARGS(__VA_ARGS__), __VA_ARGS__) 

// removed: __asm__(".readonly__" #location "__" #name) 
#define CreateReadOnlyBlockImpl(name, location, size, ...)  \ 
    template<>             \ 
    const unsigned int ReadOnlyBlock<location, size>::Data[]  \ 
    = { __VA_ARGS__ };           \ 
    ReadOnlyBlock<location, size> name; 


#define CreateReadOnlyBlock(name, ...)         \ 
    CreateReadOnlyBlockImpl(name, __COUNTER__, INC_COUNTER(__VA_ARGS__), __VA_ARGS__); 

template<int Location, int Size> struct ReadOnlyBlock 
{ 
    static const unsigned int Data[Size]; 
    int loc() const { return Location; } 
    int size() const { return Size; } 
}; 

CreateReadOnlyBlock(readOnlyArray1, 0, 1, 2, 3); 
CreateReadOnlyBlock(readOnlyArray2, 4, 5, 6, 7); 
CreateReadOnlyBlock(readOnlyArray3, 9); 
CreateReadOnlyBlock(readOnlyArray4, 1, 2, 3, 4, 5); 

int main() 
{ 
    std::cout << "@" << readOnlyArray1.loc() << ": " << readOnlyArray1.size() << '\n'; 
    std::cout << "@" << readOnlyArray2.loc() << ": " << readOnlyArray2.size() << '\n'; 
    std::cout << "@" << readOnlyArray3.loc() << ": " << readOnlyArray3.size() << '\n'; 
    std::cout << "@" << readOnlyArray4.loc() << ": " << readOnlyArray4.size() << '\n'; 
} 

On ideone this prints:

@0: 4 
@4: 4 
@8: 1 
@9: 5 
+0

Thật không may, các mảng là lớn như 1k từ, nhưng tôi thực sự thích giải pháp này. Tôi nên làm rõ điều đó, xin lỗi. Tôi đã chỉnh sửa bài đăng của mình. –

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