3

以下は、ほとんど動作するコードです。私がやりたいことは、破棄時に内容を自動削除するメモリ プールを作成し (単純な古いデータに対してのみ機能する場合は問題ありません)、プールがその内容へのポインターよりも常に長く存続する必要があることをコンパイル時に保証することです。これを達成しようとして、ポインタがその型の一部を指すプールを持つようにしました。私の戦略はうまくいくように見えますが、C++ ではテンプレート パラメーターとして定数データまたはグローバル データしか許可されていないため、思い通りにプログラミングすることができません。たとえば、以下のコードでは、メモリ プールはグローバル値である必要があります。非定数およびローカル データに対して、C++ で依存型を偽装するにはどうすればよいですか?

コードと、その使用方法を示す簡単な例を次に示します。アライメントの問題を扱っていないことをお詫びしますが、これは単純な概念実証にすぎません。

#include <iostream>
#include <cstdlib>


class pool;

template<typename T, pool& H>
class reference;


class pool {
private:
 pool(const pool&);
 pool& operator=(const pool&);

 const pool* operator&() const;
 pool* operator&();


 size_t size; 
 void *storage;

 size_t tag;

public:
 pool() : size(0), storage(0) { }
 ~pool() { free(storage); }

template<typename, pool&> friend class reference;
template<typename T, pool& H> friend reference<T, H> allocate();
};


template<typename T, pool &H>
class reference {
private:
 reference();

 size_t index;

 reference(size_t _index) : index(_index) { }

public:
 friend class pool;

 void set(const T& rvalue) const {
  *((T*)&((char*)H.storage)[index]) = rvalue;
 }

 T operator*() const {
  return *((T*)&((char*)H.storage)[index]);
 }

 reference<T, H>& operator++() {
  index += sizeof(T);
  return *this;
 }

template<typename U, pool& I> friend reference<U, I> allocate();
};

// TODO: Add in alignment stuff
template<typename T, pool& H>
reference<T, H> allocate() {
 const size_t old_size = H.size;

 H.size += sizeof(T);
 H.storage = realloc(H.storage, H.size);

 return reference<T, H>(old_size);
}


template<pool& H>
reference<char, H> get_line() {
 const reference<char, H> start = allocate<char, H>();
 reference<char, H> end = start;

 char input;

 for (;;) {
  input = std::cin.get();

  if ('\n' == input) {
   break;
  }

  end.set(input);
  end = allocate<char, H>();
 }

 end.set('\0');

 return start; 
}

template<pool &H>
std::ostream& operator <<(std::ostream& out, reference<char, H> start) {
 for (; *start != '\0'; ++start)
  std::cout.put(*start);

 return out;
}


pool input_pool;

int main(int argc, char **argv) {

 std::cout << "What is your name?" << std::endl;

 const reference<char, input_pool> input_string = get_line<input_pool>();

 std::cout << "Hello " << input_string << "!" << std::endl;


 return 0;
}
4

1 に答える 1

0

これが役立つかどうかはわかりませんが、次のようにコンパイルされます。

class pool {};

template<pool& H>
class reference {
};

struct pools {
  static pool hopefullyStaysInCache;
  static pool hopefullyStaysInMemory;
  static pool canSwapOutToDisk;
};

main(){
  reference<pools::hopefullyStaysInMemory> y;
}

プールは削除できないため、プールがすぐに削除されることはありません。プールのストレージは削除することができます。これにより、プールを維持することを気にしないほど十分に小さくすることができます。また、プール内の最後の参照が破棄されたときに削除が自動的に行われるようにすることができます。

于 2013-01-03T04:21:06.213 に答える