1

我正在尝试创建一个相对类型安全(但动态)且高效的概念,称为“可链接属性”。可链接属性类似于 C# 绑定属性的能力,并且类似于信号/插槽模型。

可链接属性是一种可以将自身链接到其他类型的值的类型。当任何值更改时,所有值都会更新。当您需要同时更新多个属性/值时,这很有用。设置链接后,一切都会为您处理好。

  1. 可以从任何类型链接到任何其他类型(理论上,这就是问题所在)
  2. 链接使用链表而不是列表。这在内存和速度上都更有效,并且使用这种方法的真正好处。
  3. 转换器用于将值从一种类型转换为另一种类型(从 1,必需,也是一个问题)
  4. 可以像 getter 和 setter 一样工作。

我正在努力解决的问题是编写链接和转换为任何类型的能力。以下代码进行了微小的更改(将模板化的 Chain 函数转换为非模板化版本并在函数中更改Chain<F>为)。问题是,链接没有正确调用。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 回答