5

配列のように見えるクラスを作成しましたが、プログラム自体にデータを保持するのではなく、ファイルからバイトをストリーミングします (RAM への影響を軽減するため)。これですべてが機能しましたが、プログラマーは次を使用してクラスを定義する必要があります。

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

例:

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

これは組み込みプロセッサ用であり、asm ディレクティブはアセンブラのツールを経由して読み取り専用ファイルを作成することに注意してください。

ここに私の質問があります。「場所」変数と「サイズ」変数を削除するにはどうすればよいですか? 私は、プログラマーがそれらを手動で入力しなければならないことを嫌い、コンパイル時にそれらを生成する何らかの方法を好んでいます。したがって、プログラマーが次のように入力する必要はありません。

//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); 

次のように入力するだけです。

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

そして、適切な定数が生成されます。基本的に、コンパイル時に以前の定義に基づいてこれらの定数を生成して配置する方法を探しています。C ++ 11は公正なゲームです。私はそれにひどく慣れていません(constexprの何かがもっともらしいですか?)。また、C-Preprocessor も、以前よりも醜くならなければ問題ありません。これは可能ですか?

明確にするために編集:

ReadOnlyBlock クラスには、次のメソッドがあります。

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

ロケーション変数と ROM ファイルの間には固有の相互依存関係があり、それをどのように壊すかは考えられません。ツール チェーンも完全に制御できますが、アセンブラー ツールにファイルの作成方法を渡す方法と、ブロックがファイル内のどこにあるかを C++ コードに示す方法が必要です。

別の編集:

ファイルとそのブロックは非常に大きくなる可能性があり、1,000 ワードにも及ぶため、多くのプリプロセッサ マジックが機能しなくなる可能性があります。また、これまでご協力いただきありがとうございました。

4

4 に答える 4

1

名前(そのフラグメント)を生成するための完全な解決策はまだわかりません#locationが、残りについては、次のようなものを使用できると思います。

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__)> \
{};
于 2013-03-21T18:15:12.897 に答える
0

以下が当てはまる場合:

  • 他の場所では使用しませ__COUNTER__
  • すべてのアレイの最大長は5です
  • すべての配列はまったく同じファイルで定義されています

次に、これを行うことができます:

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

ideoneでは、これは次のように出力します。

@0: 4
@4: 4
@8: 1
@9: 5
于 2013-03-21T18:22:36.693 に答える
0

少し把握しているかもしれませんが、va_args の代わりに可変個引数テンプレートを使用することは可能でしょうか? 何かのようなもの

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

基本的に、「場所」が必要な場所ならどこでも T1 を使用します。「サイズ」が必要な場合は、sizeof(TV) + 1 を使用します。これをテストするための適切なコンパイラはありませんが、考慮すべきことかもしれません...

于 2013-03-21T18:14:24.343 に答える
0

それは役立つかもしれません。DEF_BLOCK(size)ブロック宣言の前に追加できるブロックを数えるためにいくつかのことを書きました。私の例を書き直して、私のブロック内にデータを割り当てることができます

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;
}
于 2013-03-21T18:14:45.983 に答える