使用模板评估任何类型或功能

时间:2012-03-25 15:55:35

标签: c++ templates boost

我放弃所有以前写过的文件问题,在有意义的事情中得到清理,编辑2是当前的状态:

我目前正在为我的大学课程设计一个简单的GUI系统,我提出了一个简单的想法和问题。我在考虑一种动态标签:

我认为如果“动态”标签类可以简单地绑定每种类型的函数或指针以在每一帧自动打印它们,而不是将每一帧的值/字符串传递给“静态”标签。

这里有一些伪代码来演示,我想要实现的目标:

/* OLD WAY */
// called on initialization:
CView* pView = new CView();
CLabel* pLabel = new CLabel(10,20,"TEST");
pView->Attach(pLabel);
GUIManager->SetActive(pView);
// ...
// called every frame somewhere:
pLabel->SetText(AppTime->GetFPS()); //(AppTime is a singelton with time informations)

/* NEW WAY */
// called on initialization:
CView* pView = new CView();
//(the return type of GetFPS is float)
CDynamicLabel<float>* pDLabel = new DynamicLabel<float>(10,20, *AppTime->GetFPS());
// not only functions or member functions, this should also be possible
CDynamicLabel<int>* pDLabel2 = new DynamicLabel<int>(20,20, ptrToSomeInteger);

所以我认为必须有一种方法来结合C ++模板系统和boost :: bind来获得我想要的功能,但我无法弄清楚如何。 我希望有人能给我一些关于如何实现这一目标的提示。也许还有另一种方法可以让这种功能更常见。

编辑: 要清除一些内容,尚未实现与动态标签相关的C ++代码。我仍在努力寻找实现它的完美方法,但要澄清一些关于我当前类层次结构的事情:

我有一个虚拟类CElement,每个GUIElement都派生自。有虚拟函数用于渲染,更新(以传递的时间作为参数)和OnEvent函数,事件作为参数。通用可见性函数也在CElement类中实现。 CView是一个代表CElements特定设置的类。 GUIManager是一个Singleton,它将所有调用转发给当前视图和相关元素。

我的基本想法是因为GUI系统是游戏的一部分,如果有一种通用的方式来实现自我更新标签而不是为某个标签编写另一个派生类,那么无论如何都会在每一帧调用更新函数。只需将fps打印到屏幕或类似屏幕上即可。

我希望以某种方式澄清事情......

EDIT2: / *因为代码无法正常工作而被删除... * /

EDIT3: 一切正常,我使用boost :: function和boost :: bind并编写了一个模板,现在可以做我想做的一切......

3 个答案:

答案 0 :(得分:1)

您是否会提供有关用例的更多详细信息?

AFAICT,在您提供的示例中,该值必须在某处转换为文本,以便可以将值呈现到屏幕上。是

所以我可以理解将指针或引用传递给将被渲染到标签中的文本。然后'用户端'程序可以在创建标签后更改文本。但这确实留下了未定义标签如何知道它必须重新渲染文本。所以这不太理想。

我也可以理解将函数指针传递给标签。该函数将返回(指向)要呈现的文本片段。这很有用,因为该函数会在值发生变化时执行,并相应地将值转换为文本。

同样,未定义标签如何知道它需要调用该函数。但假设尝试过的标签可以解决这个问题,那就完全是同一个问题,所以我认为这个问题已经解决了。

这似乎是唯一必要的案例。其他一切似乎都可以使用它。因此标签可以在函数上进行模板化,隐藏类型,而不是值的数据类型,这是无关紧要的,因为它必须转换为文本。

这样做的另一个好处是功能可以确保格式看起来正确。我喜欢像帧时间这样渲染为固定宽度字段的东西,如果它收缩和变宽则很难看。

这是一个模板类,它具有用于“用户端”程序的类型特定访问器以设置和更新值,以及一个返回要呈现的字符串的固定函数。

摘要:函数上的模板,它返回一个文本字符串或模板,该类具有定义良好的函数,该函数返回文本字符串。

编辑(由于披萨) 这可能是一种有用的思考方式。

解决问题的优雅方法是'接口'(如Java,或Golang,或......)。

在这种情况下,接口只需要一个无参数的函数,它返回(在我的例子中)一个文本字符串。它是传递给标签的界面。

接口需要嵌入一个值,引用或指向实现该值的对象(类实例或POD),并且该类或POD需要有一种方法来提供文本字符串。

实现该值的类或POD被接口隐藏在标签之外。

答案 1 :(得分:0)

我不知道你的类层次结构,但这是一个通用的想法:

#include <type_traits>

struct CLabel { virtual ~CLabel() { } /* ... */ };

template <typename T>
struct DynamicLabel : CLabel
{
    DynamicLabel(T);
    // ...
};

template <typename T>
CLabel * LabelMaker(T x)
{
    return new DynamicLabel<typename std::remove_reference<T>::type>(x);
}

现在你可以使用:

CLabel * p = LabelMaker(12U), * q = LabelMaker(1.5L);

答案 2 :(得分:0)

对于每个想要做类似事情的人来说,这是我提出的最终简单测试代码,它说明了功能:

/* DynamicLabel.hpp */
template <class T> class CDynamicLabel : public CElement
{    
public:
    CDynamicLabel(void) {}
    CDynamicLabel(boost::function0<T> f) : m_f(f) {}
    void TestCall(void) const { cout << m_f(); }
private:
    boost::function0<T> m_f;
};
/* Test Code in Main (MEMFUNC is a Macro to simplify binding and AppTime is a definition to simplify the CAppTime-Singleton calls) */
CDynamicLabel<float> TestDL(MEMFUNC(&CAppTime::GetLastGPUDelta, AppTime));
TestDL.TestCall();