我正在尝试将模板与泛型结合,重点是尽可能快地(合理地)访问原始/值类型属性,最好将其保存在C ++ / CLR中。考虑这个简单的模板:
template< typename type >
class value_wrapper {
public:
type value;
};
及其对应部分:
generic< typename T >
public ref class ValueWrapper {
...
public:
property T Value {
T get() {
if( T::typeid == System::Int32::typeid )
return ( T )( ( value_wrapper< int > * )ptr )->value;
...branches for some other types...
// if all else fails:
return ( T )( Object ^ )( ( value_wrapper< gcroot< Object ^ > > * )ptr )->value;
}
...
}
...
private:
void *ptr;
};
问题1。当将通用的MSIL转换为值类型的特化时,代码是否进一步优化?是否有可能以这样的方式检查类型:例如,在非{int}类型的ValueWrapper<int>
分支中,类型比较本身是否会被优化掉?
现在,在每个方法中列出所有支持的类型都有点痛苦,所以我为此创建了一个单独的函数:
template< typename action, typename context_type >
__forceinline
static bool apply( System::Type ^type, void *value, System::Object ^*box, context_type context ) {
if( type == System::Int32::typeid )
return action().operator()< int >( ( int * )value, context ), true;
...branches for some other types...
// if all else fails:
return action().operator()< gcroot< System::Object ^ > >( box, context ), false;
}
struct get_value {
template< typename type, typename result_type >
void operator () ( result_type *result, void *ptr ) {
*result = ( ( value_wrapper< type > * )ptr )->value;
}
};
generic< typename T >
public ref class ValueWrapper {
...
property T Value {
T get() {
T result;
System::Object ^box;
return apply< get_value >( T::typeid, &result, &box, ptr ) ? result : ( T )box;
}
...
}
...
};
事实证明,这比原始代码慢约3倍。
问题2。这里有什么可以改变以允许优化器使第二个实现速度更接近第一个(理想情况下,速度差在10%-20%之内)?
P.S。这主要是关于VC 2010.但是如果VC 2012在这方面有所不同,那也很有用。
答案 0 :(得分:0)
经过一些修补和MSIL眼球之后,我得到了第二个问题的答案:只需传递typeid
getter函数而不是typeid
本身。框架似乎更容易请求每个比较的类型信息,而不是将其存储到某个变量(旧的type
参数)并重用它。
通过这种方法,减速从3倍下降到5-10%(!)。
问题2,问题1待决。
结果代码:
template< typename action, typename context_type >
__forceinline
static bool apply( System::Type ^type(), void *value, System::Object ^*box, context_type context ) {
if( type() == System::Int32::typeid )
return action().operator()< int >( ( int * )value, context ), true;
if( type() == SupportedStruct::typeid )
return action().operator()< SupportedStruct >( ( SupportedStruct * )value, context ), true;
if( type() == System::String::typeid )
return action().operator()< std::wstring >( ( System::String ^* )value, context ), true;
// for both reference types and unknown value types:
return action().operator()< gcroot< System::Object ^ > >( box, context ), false;
}
struct get_value {
template< typename type, typename result_type >
void operator () ( result_type *result, void *ptr ) {
*result = ( ( value_wrapper< type > * )ptr )->value;
}
template< typename type >
void operator () ( System::String ^*result, void *ptr ) {
*result = gcnew System::String( ( ( value_wrapper< type > * )ptr )->value.c_str() );
}
};
generic< typename T >
public ref class ValueWrapper {
...
public:
property T Value {
T get() {
T result;
System::Object ^box;
return apply< get_value >( TypeGetter, &result, &box, ptr ) ? result : ( T )box;
}
...
}
...
private:
void *ptr;
private:
static System::Type ^TypeGetter() {
return T::typeid;
}
};