我正在尝试创建一个名为“可链接属性”的相对类型安全(但动态)且高效的概念。可链接属性类似于C#绑定属性的能力,类似于信号/插槽模型。
可链接属性是一种可以将自身链接到其他类型的值的类型。当任何值更改时,所有值都会更新。当您需要同时更新多个属性/值时,这非常有用。设置链接后,一切都会为您完成。
我正在努力解决的问题是编写链接和转换为任何类型的能力。以下代码适用于较小的更改(将模板化的Chain函数转换为非模板化版本,并在Chain<F>
函数中将Chain
更改为SetLink
。问题是,没有正确调用链接。
这个类几乎可以工作(它确实可以编译运行但是没有按预期工作。如果没有上面的更改,绑定函数永远不会调用。它只是测试代码而没有正确编码(请不要评论使用静态计数器,它只是一个临时修复。)链和链接元素是至关重要的方面。
Chain简单地假设转换并更新属性的值,然后将它(或可能是原始值)传递给下一个属性。这种情况一直持续到一个人回到原来的财产,在这种情况下它会终止。
#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;
}
答案 0 :(得分: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;
}
注意:有一些链接错误意味着更新会触发超过必要的次数 - 您应该检查...