微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 将模板对象存储为成员对象

假设你有一些这样的代码
struct Manager
{
  template <class T> 
  void doSomething(T const& t)
  {
    Worker<T> worker;
    worker.work(t);
  }
};

一个“管理器”对象被创建一次,并使用一些不同类型“T”进行调用,但每个类型T被调用多次.这可能是一个简化的形式

Manager manager;
const int N = 1000;
for (int i=0;i<N;i++)
{
  manager.doSomething<int>(3);
  manager.doSomething<char>('x');
  manager.doSomething<float>(3.14);
}

现在,剖析表明,构建一个“工人”是一个耗时的操作,应该避免构造它N次(在doSomething< T>)内.为了线程安全的原因,可以有一个Worker< int>,一个Worker< char>和< float>每个“经理”,但不是一个工作者< int>为所有经理.所以通常我会使“worker”成员变量.但是我该如何在上面的代码中做到这一点? (我事先不知道会使用“T”).

我已经找到了一个使用std :: map的解决方案,但它并不完全是类型安全的,当然不太优雅.你可以建议一种类型安全的方式,而不需要构建“工作人员”没有虚拟方法,每“T”多一次?

(请注意,Worker不是源自任何模板参数的免费基类).

谢谢任何解决方案!

解决方法

您可以使用类似std :: map< std :: type_info,shared_ptr< void> >喜欢这个:
#include <map>
#include <typeinfo>
#include <utility>
#include <functional>
#include <boost/shared_ptr.hpp>

using namespace std;
using namespace boost;

// exposition only:
template <typename T>
struct Worker {
    void work( const T & ) {}
};

// wrapper around type_info (Could use reference_wrapper,// but the code would be similar) to make it usable as a map<> key:
struct TypeInfo {
    const type_info & ti;
    /*implicit*/ TypeInfo( const type_info & ti ) : ti( ti ) {}
};

// make it LessComparable (Could spcialise std::less,too):
bool operator<( const TypeInfo & lhs,const TypeInfo & rhs ) {
    return lhs.ti.before( rhs.ti );
}

struct Manager
{
    map<TypeInfo,shared_ptr<void> > m_workers;
    template <class T> 
    Worker<T> * findWorker()
    {
        const map<TypeInfo,shared_ptr<void> >::const_iterator
        it = m_workers.find( typeid(T) );
        if ( it == m_workers.end() ) {
            const shared_ptr< Worker<T> > nworker( new Worker<T> );
            m_workers[typeid(T)] = nworker;
            return nworker.get();
        } else {
            return static_cast<Worker<T>*>( it->second.get() );
        }
    }
    template <typename T>
    void doSomething( const T & t ) {
        findWorker<T>()->work( t );
    }
};

int main() {

    Manager m;
    m.doSomething( 1 );
    m.doSomething( 1. );

    return 0;
}

这是类型安全的,因为我们使用type_info作为地图中的索引.而且,即使它们在shared_ptr< void>中,工作者也被正确删除,因为删除者是从原始的shared_ptr< Worker< T>并且那个调用正确的构造函数.它也不使用虚拟函数,虽然所有类型的擦除(和这是一个)在某处使用类似虚拟函数.这里是shared_ptr.

将来自findWorker的与模板无关的代码转换为非模板函数以减少代码膨胀留给读者的练习:)

感谢所有评论者指出使用type_info作为键的错误.

原文地址:https://www.jb51.cc/c/112686.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐