0

プロセッサレジスタとその操作のプレースホルダーを実装できるクラス階層を見つけようとしています。また、実行時に定数を折りたたむことができるようにする必要があります。簡単にするために、ここでは乗算という1つの演算のみを見ていきます。プレースホルダーと定数は、均一にアクセスできる必要があります。つまり、共通の基本クラスを持っている必要があります。

以下のコードは、次のクラスを定義します。

class A:プレースホルダー(レジスター)と定数の基本クラス

class B:レジスターのプレースホルダー(その構造はその名前を保持します)

class C:すべての定数のベース

class CIint定数

class CFfloat定数

#include <iostream>
#include <memory>
#include <cassert>

class A {
public:
  virtual ~A(){}
};

class B : public A {
};

class C : public A {};

class CI : public C {
public:
  typedef int Type_t;
  int getValue() {return 1;}
};

class CF : public C {
public:
  typedef float Type_t;
  float getValue() {return 1.1;}
};




typedef std::shared_ptr<A> Aptr;
typedef std::shared_ptr<B> Bptr;
typedef std::shared_ptr<C> Cptr;
typedef std::shared_ptr<CI> CIptr;
typedef std::shared_ptr<CF> CFptr;


template<class T, class T2> struct promote {};
template<> struct promote<float,int>   { typedef float Type_t; };
template<> struct promote<float,float> { typedef float Type_t; };
template<> struct promote<int,float>   { typedef float Type_t; };
template<> struct promote<int,int  >   { typedef int   Type_t; };


template<class T1, class T2>
typename promote<typename T1::element_type::Type_t,
         typename T2::element_type::Type_t>::Type_t
mul_const( const T1& c1 , const T2& c2 )
{
  std::cout << c1->getValue() * c2->getValue() << "\n";
  return c1->getValue() * c2->getValue();
}



template<class T>
std::shared_ptr<T> get(const Aptr& pA) {
  return std::dynamic_pointer_cast< T >( pA );
}


Aptr create_A(float f) { return std::make_shared<A>(); }
Aptr create_A(int i)   { return std::make_shared<A>(); }


Aptr mul_const( const Cptr& cp1 , const Cptr& cp2 )
{
  if (auto c1 = get<CI>(cp1))
    if (auto c2 = get<CF>(cp2)) {
      return create_A( mul_const(c1,c2) );
    }
  if (auto c1 = get<CF>(cp1))
    if (auto c2 = get<CI>(cp2)) {
      return create_A( mul_const(c1,c2) );
    }
  if (auto c1 = get<CI>(cp1))
    if (auto c2 = get<CI>(cp2)) {
      return create_A( mul_const(c1,c2) );
    }
  if (auto c1 = get<CF>(cp1))
    if (auto c2 = get<CF>(cp2)) {
      return create_A( mul_const(c1,c2) );
    }
  assert(!"oops");
}



Aptr mul( const Aptr& pA1, const Aptr& pA2 ) 
{
  if (auto c1 = get<C>(pA1))
    if (auto c2 = get<C>(pA2)) 
      {
    return mul_const(c1,c2);
      }
}


int main()
{
  Aptr pA1( new CF );
  Aptr pA2( new CI );

  Aptr result = mul( pA1, pA2 );
}

上記のコードで私が抱えている問題は関数Aptr mul_const( const Cptr& cp1 , const Cptr& cp2 )です。基本的に、定数タイプのすべての可能な組み合わせに対するタイプの切り替えが含まれています。それは動作しますが、これがよりエレガントに実行できるかどうか知りたいですか?

4

1 に答える 1

1

コンパイラが行うことを行うことができ、一方がフロートの場合、もう一方のパラメーターをフロートに変換できると思います。おそらく、変換と「isFloat」(または「isInt」) を行うための新しい関数が必要になるでしょう。私はそれがあなたに多くの利益をもたらすとは確信していません、本当に...

// Add two virtual member functions here:
class C : public A {
    public:
       virtual bool isInt() = 0;
       virtual float getAsFloat() = 0;
};

次に実装します。

class CI : public C {
public:
  typedef int Type_t;
  int getValue() {return 1;}
  float getAsFloat() { return getValue(); }
  bool isInt() { return true; }
};

class CF : public C {
public:
  typedef float Type_t;
  float getValue() {return 1.1;}
  float getAsFloat() { return getValue(); }
  bool isInt() { return false; }
};

これで、mul_const は次のようになります。

Aptr mul_const( const Cptr& cp1 , const Cptr& cp2 )
{
  if (cp1.isInt() && cp2.isInt())
  {
     CIptr c1 = get<CI>(cp1));
     CIptr c2 = get<CI>(cp2));
     std::cout << c1->getValue() * c2->getValue() << "\n";
     return CIptr(c1->getValue() * c2->getValue());
  }
  else
  {
     std::cout << cp1->getAsFloat() * cp2->getAsFloat() << "\n";
     return CFptr(cp2->getAsFloat() * cp2->getAsFloat());
  }
  // This becomes unreachable... Probably OK to delete.
  assert(!"oops");
}

[そして、いくつかのテンプレートパーツを削除できると思います...]

于 2013-03-03T00:32:28.720 に答える