我怀疑在这里可能会被指责为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_a
和render_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 );
}
希望代码足够清晰。
答案 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
,会不会更好?这应该没有性能问题