模板功能与一些非常见的部分

时间:2013-12-11 08:59:03

标签: c++ templates

我怀疑在这里可能会被指责为OT,请原谅我。 - 以防万一 -

我有一个小问题,我觉得这个问题与真正的编程问题一样,但仍然让我感到不舒服,我希望得到一些专家意见。

假设我们使用的模板函数对于允许操作的所有可能类型T的行为方式几乎相同:

//Perform the rendering
template< typename T >
long drawing_facility::render( typename object_cnt< T >::type& elements, draw_type type )
{
    ....
    //Any computation needed?
    if( !obj->render_init_done.test_and_set( std::memory_order::memory_order_acquire ) )
    {
        ....
    }
    ....
}

在这段代码中,除了if语句之外,我跳过了我认为不必要的所有内容。 if检查处理对象中的原子标志,以确定是否需要特殊的“计算”,如果需要,则在继续执行“常见”任务之前必须进行某些操作。

我的问题是render是一个模板,对于所有可能和允许的T,应该以相同的方式运行,但是如果render_init_done设置为false,则会出现不同的情况需要完成,if中的代码并不适用于所有T

我通过向模板添加第二个参数来快速解决了这个问题,该参数告诉代码模板正在处理哪种类型,并在此基础上在if中执行不同的操作。

我真的怀疑这不是解决问题的最优雅方式,您对如何以不同方式管理此功能有任何意见吗?

我想避免大量复制,也要避免太多函数调用,这样的事情应该可以完成这项任务:

//Perform the rendering
template< typename T >
long drawing_facility::render( typename object_cnt< T >::type& elements, draw_type type )
{
    render_part_a< T >( elements );
    //Any computation needed?
    if( !obj->render_init_done.test_and_set( std::memory_order::memory_order_acquire ) )
    {
        ...
    }
    render_part_b< T >( elements );
}

//Perform the rendering, part a
template< typename T >
long drawing_facility::render_part_a( typename object_cnt< T >::type& elements )
{
    ...
}

//Perform the rendering, part b
template< typename T >
long drawing_facility::render_part_b( typename object_cnt< T >::type& elements )
{
    ...
}

但这是解决问题的更好方法吗?现在调用render意味着另外两个函数调用,这应该不是很多,直到我可以保证render_part_arender_part_b的独立性,实际上我可以,但只有一些肮脏的黑客和微妙的参数传递解决方法。

由于

小更新:在@Nim的建议之后,我认为可以使用一些重载函数解决问题,请看看这个非常基本的例子,我从渲染中删除了第二个参数 - 不再需要 - :

typedef enum draw_type {
    draw_text = 0,
    draw_vertex = 1
} draw_type;

class drawable
{
public:
    virtual void foo() = 0;
};

class text : drawable
{
public:
    void foo() {};
};

class vertex : drawable
{
public:
    void foo(){};
};

template< typename T >
class drawable_object
{ };

template< typename T >
struct object_cnt
{
    typedef std::vector< std::shared_ptr< drawable_object< T > > > type;
};

class drawing_facility
{
    void special( drawable_object< text >* obj )
    {
         std::cout<<"text\n";
    }
    void special( drawable_object< vertex >* obj )
    {
        std::cout<<"vertex\n";
    }
    public:
        template< typename T >
        long render( typename object_cnt< T >::type& elements )
        {
            //...
            for( auto obj : elements )
            {
                //...
                //the 'if' statement should be here.
                special( obj.get() );
                //...
            }
       //...
       }
};

int main()
{
    typename object_cnt< text >::type a;
    a.push_back( shared_ptr< drawable_object< text > >() );
    typename object_cnt< vertex >::type b;
    b.push_back( shared_ptr< drawable_object< vertex > >() );
    drawing_facility draw;
    draw.render< text >( a );
    draw.render< vertex >( b );
}

希望代码足够清晰。

2 个答案:

答案 0 :(得分:1)

你采用的第二种策略对我没有意义......

我会使用你原来的方法,但是对于专门的计算,为每个T重载一个函数,例如..

struct A{}; struct B{}; struct C{};

void compute(A& obj)
{ 
  // code for A
}

void compute(B& obj)
{ 
  // code for B
}

void compute(C& obj)
{ 
  // code for C
}

template <typename T>
void render(T& obj)
{
  .. // common stuff

  if (!obj.computed())
  {
    // now call overloaded function
    compute(obj);
  }

  .. // common stuff
}

答案 1 :(得分:0)

如果在代码中使用内联模板专门化功能而不是if,会不会更好?这应该没有性能问题