我们有一个日志框架,允许我们自动添加特定于上下文的信息来记录消息。
这是通过继承off Context
类模板来实现的,该模板使用CRTP pattern
/ static polymorphism
调用子类上的Token()
函数来获取对象的上下文。< / p>
登录时,我们使用扩展为GetLog()
的宏。
GetLog
时,它获取记录器并添加上下文Token
。Context
- 派生类中时,在全局命名空间中找到GetLog
,它只是获得记录器。下面有一个完整的例子。
问题
我的问题是,如果我有一个类模板,而该模板又从Context
派生,例如:
template<typename T>
struct Foo : Context<Foo<T>>;
当我尝试在成员函数中登录时,我必须在LOG
前加this->
前缀,以使方法GetLog()
成为依赖名称。< / p>
我有没有办法让类模板成员函数使用不LOG
的{{1}}并让它解析为this->
?
思想
Context::GetLog()
成为虚函数,并使用动态多态来获取上下文。缺点是这会在每次日志记录调用中添加一个v表查找(有很多Token
派生对象,编译器能够内联吗?)我想尽可能地使它更精简。Context
和std::enable_if
区分std::is_base_of
和Context
派生对象。我不认为我能用这个免费功能吗?这是一个工作范例:
non-Context
答案 0 :(得分:3)
您可以使用使用声明明确将Context::GetLog
带入派生类的范围:
template<typename T>
struct Foo : Context<Foo<T>>
{
using Context<Foo<T>>::GetLog;
// the rest as before
};
答案 1 :(得分:1)
嗯,有一个简单的解决方案,但它需要在Context派生类中进行一些额外的工作。
您可以使用基类名称而不是this->
进行限定,因此例如使用Context<Foo<T>>::GetLog
足以向编译器指示查找是否依赖(并且必须延迟到实例化)。
不幸的是,由于Context
本身就是一个模板,所以它有点笨拙;所以我们将使用另一个类(我在这里称之为Base
):
// 1. Wrap the generic GetLog into a `Base` class:
struct Base {
static Log& GetLog() { return glog; }
};
// 2. Introduce a typedef into the derived class:
template <typename T>
struct Foo: Context<Foo<T>> {
typedef Context<Foo<T>> Base;
...
};
// 3. Change the macro
#define LOG Base::GetLog()
此处,Base
查找遵循典型的范围规则,并找到最近的Base
...在最坏的情况下默认为全局范围中存在的范围。
完全正常运行的演示位于ideone。