具有一些非公共部分的模板函数

Template function with some non common part

本文关键字:函数 公共部 具有一      更新时间:2023-10-16

我怀疑我可能是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 s来说并不常见。

我通过在模板中添加第二个参数很快解决了这个问题,这个参数"告诉"代码模板正在处理哪种类型,在此基础上在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的建议下,我认为使用一些重载函数可以解决这个问题,请看看这个非常基本的例子,在这个例子中,我从render中删除了第二个参数-不再需要-:

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<<"textn";
    }
    void special( drawable_object< vertex >* obj )
    {
        std::cout<<"vertexn";
    }
    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 );
}

希望代码足够清晰。

你采用的第二种策略对我来说没有意义…

我确实会使用您原来的方法,但对于专门的计算,例如,为每个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
}

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