静态const全局仿函数实例

时间:2015-09-24 06:38:34

标签: c++ static shared-ptr functor

声明函数对象的全局实例的最佳方法是什么,以便我可以在整个程序中导入和使用实例作为callable?

具体来说,我创建了一个模板类,用作共享指针的自定义删除器。需要使用" Free"删除第三方库中的几种指针类型。引用指针的函数。该类的实例使用要删除的指针的类型进行实例化,并指向具有Free函数签名的函数的指针。我将实例声明为const,因为成员函数指针不需要更改。

template <class T>
class Deleter {
public:
  typedef typename bool(CALLING_CONVENTION *DeleterFunc)(T**);
  Deleter(DeleterFunc deleter) : deleter_(deleter) {}
  void operator() (T* t) { if (t) { deleter_(&t) }

private:
  DeleterFunc deleter_;
};

static const Deleter<I_x> x_deleter(FreeXInterface);

我的第一次尝试是.h文件中每个指针类型的创建实例,但如果我在其他代码中包含此头文件,则会产生多个定义的符号。所以我将实例的声明更改为&#34; static&#34;这编译似乎工作正常,但我已经看到警告,这不是一个好主意(特别是如果对象属于命名空间)因为静态导致链接只是文件,并且每个编译单元将有它自己的副本。

我的问题是,如果我真的不在乎它们是否是文件之间的相同实例,这是否重要?我没有将它用作全局数据,并且函数对象实际上没有任何状态。如果这些对象被声明为静态,我是否会担心线程?有没有更好的方法来实现它而不使用static关键字?

1 个答案:

答案 0 :(得分:0)

嗯,你的链接器问题的基本答案在这里:How do I use extern to share variables between source files?让我们尝试做得更好一点:你每次实例化一个函数时,你当前必须引用删除函数,而不是它根据类型自动选择。

当然,我们经常根据类型选择 types std::vector<int>是能够保存int的动态数组。链接在那里不是一个大问题:一切都或多或少内联,每个翻译单元提到std::vector<int>::push_back()获取自己的目标代码副本以将int放入int的向量中,并且链接器(有时)帮助删除重复的实例化。但在这里我们想要一个对象,而不是一个类型。

那么模板和全局对象之间的中途是什么?模板类的静态成员!检查一下:

// Deleter.h

typedef typename bool(CALLING_CONVENTION *DeleterFunc)(T**);

template <class T>
class Deleter {
public:
    static DeleterFunc s_deleterFunc;

    void operator() (T* t) {
        if(t) { s_deleterFunc(&t); }
    }
};

// XDeleter.cpp

#include "Deleter.h"
template<>
DeleterFunc Deleter<I_x>::s_deleterFunc = FreeXInterface;

// YDeleter.cpp

#include "Deleter.h"
template<>
DeleterFunc Deleter<I_y>::s_deleterFunc = FreeYInterface;

对于您想要删除器的每种类型,您只需为专用类提供静态成员的实例化。调用Deleter<I_x>::operator()的代码只需要包含Deleter.h;链接器将负责将其与XDeleter.cpp中声明的那个匹配。

请注意,我使用模板化的类而不是模板化的函数,只是因为它允许您使用函数指针。但你可以做一些简单的事情:

// Deleter.h

template <class T>
invokeDeleter(T* t);

// XDeleter.cpp

#include "Deleter.h"
template<>
invokeDeleter<I_x>(I_x* x)
{
    ...
}

// YDeleter.cpp

#include "Deleter.h"
template<>
invokeDeleter<I_y>(I_y* y)
{
    ...
}