消除类模板中的基类名称

时间:2013-05-02 05:40:42

标签: c++ logging

我们有一个日志框架,允许我们自动添加特定于上下文的信息来记录消息。

这是通过继承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派生对象,编译器能够内联吗?)我想尽可能地使它更精简。
  • 使用Contextstd::enable_if区分std::is_base_ofContext派生对象。我不认为我能用这个免费功能吗?
  • 还有其他方式吗?

这是一个工作范例:

non-Context

2 个答案:

答案 0 :(得分:3)

您可以使用使用声明明确将Context::GetLog带入派生类的范围:

template<typename T>
struct Foo : Context<Foo<T>>
{
    using Context<Foo<T>>::GetLog;

    // the rest as before
};

Live example

答案 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