1

「リンク可能なプロパティ」と呼ばれる、比較的タイプセーフ(ただし動的)で効率的なコンセプトを作成しようとしています。リンク可能なプロパティは、プロパティなどをバインドするC#の機能に似ており、シグナル/スロットモデルに似ています。

リンク可能なプロパティは、他のタイプの値にリンクできるタイプです。値が変更されると、すべての値が更新されます。これは、複数のプロパティ/値を同時に更新する必要がある場合に役立ちます。リンクを設定すると、すべてが自動的に処理されます。

  1. 任意のタイプから他のタイプにリンクできます(理論的には、これが問題です)
  2. リンクは、リストではなくリンクリストを使用します。これは、メモリと速度の両方でより効率的であり、このアプローチを使用することの本当の利点です。
  3. コンバーターは、値をあるタイプから別のタイプに変換するために使用されます(1から、必須、問題もあります)
  4. ゲッターとセッターのように振る舞うことができます。

私が苦労している問題は、リンクして任意のタイプに変換する機能を作成することです。次のコードは、小さな変更で機能します(テンプレート化されたChain関数をテンプレート化されていないバージョンに変換し、関数内でChange Chain<F>toに変換します)。問題は、リンクが正しく呼び出されないことです。ChainSetLink

このクラスはほぼ機能します(コンパイルと実行は行いますが、期待どおりには機能しません。上記の変更がないと、バインディング関数は呼び出されません。これはテストコードであり、適切にコード化されていません(静的カウンターの使用についてコメントしないでください。一時的な修正)チェーン要素とリンク要素は重要な側面です。

チェーンは、プロパティの値を変換して更新し、それを次のプロパティに渡す(または元の値の場合もある)と単純に想定しています。これは、元のプロパティに戻るまで続きます。元のプロパティに戻ると、プロパティは終了します。

#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/function.hpp>

using namespace std;



static int iLCount = 1;
template <typename T>
class LinkableProperty
{
    public:
        std::string Name;       
        boost::function<void(T)> Link;

        T Value;

        template<typename F>
        void Chain(F val)
        {
            Value = val;
            std::cout << this->Name << " - " << this << ", " << &Link << ", " << val << " ! " << this->Value << " - " << "\n";
            if (--iLCount < 0) return;
            if (!Link.empty()) Link(Value);
        }


        LinkableProperty() { Link = NULL; Value = T(); Name = "Level " + std::to_string(iLCount++); };

        void operator =(T value) { Value = value; }

        template<typename F> void SetLink(LinkableProperty<F> &p)
        {           
            Link = boost::bind(&LinkableProperty<F>::template Chain<F>, &p, _1);
        }

        void operator ()()
        {
            if (!Link.empty()) Link(Value);
        }

};



int main()
{

    LinkableProperty<unsigned short> L1;
    LinkableProperty<double> L2;

    L2.SetLink(L1);
    L1.SetLink(L2);

    L1 = 1;
    L2 = 1.1;

    L1();

    cout << "----------\n" << L1.Value << ", " << L2.Value << endl;     
    getchar();
    return 0;
}
4

1 に答える 1

1

問題はおそらくここから生じます:

template<typename F> void SetLink(LinkableProperty<F> p)

元のプロパティのコピーを渡します。参照(またはポインター)を受け入れるようにこれを変更すると、運が良くなる可能性があります。例えば:

template<typename F>
void SetLink(LinkableProperty<F>* p)
{           
  Link = boost::bind(&LinkableProperty<F>::template Chain<F>, p, _1);
}

期待どおりに動作するはずです...

編集:変換全体でタイプを保持する方法を示すために更新されました:

template <typename FT, typename TT>
TT convert(FT v)
{
  return v; // default implicit conversion
}

template<>
double convert(unsigned short v)
{
  std::cout << "us->d" << std::endl;
  return static_cast<double>(v);
}

template<>
unsigned short convert(double v)
{
  std::cout << "d->us" << std::endl;
  return static_cast<unsigned short>(v);
}

static int iLCount = 1;
template <typename T>
class LinkableProperty
{
  template <typename U>
  struct _vref
  {
    typedef U vt;
    _vref(vt& v) : _ref(v) {}
    U& _ref;
  };
    public:
        std::string Name;       
        boost::function<void(_vref<T>)> Link;

        T Value;

        template<typename F>
        void Chain(F const& val)
        {
            Value = convert<typename F::vt, T>(val._ref);
            std::cout << this->Name << " - " << this << ", " << &Link << ", " << val._ref << " ! " << this->Value << " - " << "\n";
            if (--iLCount < 0) return;
            if (!Link.empty()) Link(Value);
        }


        LinkableProperty() { Link = NULL; Value = T(); Name = "Level " + std::to_string(iLCount++); };

        void operator =(T value) { Value = value; }

        template<typename F>
        void SetLink(LinkableProperty<F>* p)
        {           
            Link = boost::bind(&LinkableProperty<F>::template Chain<_vref<T>>, p, _1);
        }

        void operator ()()
        {
            if (!Link.empty()) Link(_vref<T>(Value));
        }

};



int main()
{

    LinkableProperty<unsigned short> L1;
    LinkableProperty<double> L2;

    L2.SetLink(&L1);
    L1.SetLink(&L2);

    L1 = 1;
    L2 = 1.1;

    L1();

    cout << "----------\n" << L1.Value << ", " << L2.Value << endl;     
    getchar();
    return 0;
}

注:リンクのバグがいくつかあります。これは、更新が必要以上にトリガーされることを意味します。これを確認する必要があります...

于 2012-11-26T11:29:51.330 に答える