3

私はboost::variant、この質問をする必要がなく、使用できることを知っています。しかし、使用boost::variantには多くの醜いコードが含まれます。特に来客はごちゃごちゃ。だから、これ以上苦労せずに...

カリー化された関数の遅延評価を実装するために、次のテンプレート化されたクラスを作成しました。(スニペット全体については、以前の質問を参照してください。)

template <typename> class curry;

template <typename _Res>
class curry< _Res() >
{
  public:
    typedef std::function< _Res() > _Fun;
    typedef _Res _Ret;

  private:
    _Fun _fun;

  public:
    explicit curry (_Fun fun)
    : _fun(fun) { }

    operator _Ret ()
    { return _fun(); }
};

そのため、メモ化を含めるように更新したいと思います。概念的には、非常に単純です。まず、次のものを交換する必要があります。

private:
  _Fun _fun;

public:
  explicit curry (_Fun fun)
  : _fun(fun) { }

と:

private:
  bool _evaluated; // Already evaluated?
  union
  {
      _Fun _fun;   // No
      _Res _res;   // Yes
  };

public:
  explicit curry (_Fun fun)
  : _evaluated(false), _fun(fun) { }

  explicit curry (_Res res)
  : _evaluated(true), _res(res) { }

しかし、あと2つ残っています。operator _Retまず、遅延評価を実行する場合、結果が実際にメモ化されるように更新する必要があります。次に、デストラクタを追加して、 の値に応じてまたはが破棄されるよう_evaluatedにする必要があります。そして、ここで私は物事を行う方法についてよくわかりません。_fun_res

_funまず、これはに置き換える正しい方法_resですか? そうでない場合は、どうすればよいですか?

operator _Ret ()
{
  if (!_evaluated) {
    _Fun fun = _fun;

    // Critical two lines.
    _fun.~_Fun();
    _res._Res(fun());

    _evaluated = true;
  }
  return _res;
}

第二に、これは選択的に破壊する正しい方法_funですか_res? そうでない場合は、どうすればよいですか?

~curry ()
{
   if (_evaluated)
     _res.~_Res();
   else
     _fun.~_Fun();
}
4

1 に答える 1

0

他のコメント投稿者が述べているようにユニオンを使用することはできませんが、配置構文を使用することはできます。

これは、配置newを使用した識別された共用体の例です。

プラットフォームにはAタイプとBタイプの配置制限がある場合があり、これらの制限の適用はこのコードでは処理されないことに注意してください。

#include <iostream>
#include <cstring>

using namespace std;

struct foo {
  foo(char val) : c(val) {
    cout<<"Constructed foo with c: "<<c<<endl;
  }

  ~foo() {
    cout<<"Destructed foo with c: "<<c<<endl;
  }
  char c;
};

struct bar {
  bar(int val) : i(val) {
    cout<<"Constructed bar with i: "<<i<<endl;
  }

  ~bar() {
    cout<<"Destructed bar with i: "<<i<<endl;
  }

  int i;
};

template < size_t val1, size_t val2 >
struct static_sizet_max
{
   static const size_t value
     = ( val1 > val2) ? val1 : val2 ;
};

template <typename A, typename B>
struct unionType {
  unionType(const A &a) : isA(true)
  {
    new(bytes) A(a);
  }

  unionType(const B &b) : isA(false)
  {
    new(bytes) B(b);
  }

  ~unionType()
  {
    if(isA)
      reinterpret_cast<A*>(bytes)->~A();
    else
      reinterpret_cast<B*>(bytes)->~B();
  }

  bool isA;
  char bytes[static_sizet_max<sizeof(A), sizeof(B)>::value];
};

int main(int argc, char** argv)
{
  typedef unionType<foo, bar> FooOrBar;

  foo f('a');
  bar b(-1);
  FooOrBar uf(f);
  FooOrBar ub(b);

  cout<<"Size of foo: "<<sizeof(foo)<<endl;
  cout<<"Size of bar: "<<sizeof(bar)<<endl;
  cout<<"Size of bool: "<<sizeof(bool)<<endl;
  cout<<"Size of union: "<<sizeof(FooOrBar)<<endl;
}
于 2012-06-06T01:01:36.533 に答える