我正在使用libffi和我已經做了一個類似的模板std::function
(即class Func<Ret (Args...)> { /* ... */};
。我想將返回類型(Ret
)和每個參數類型(Args
)轉換爲。其相應的libffi類型(見this僅供參考)到目前爲止,我想出了這一點:模板編程:專業化和enable_if
// Member function of 'Func' class
Prepare(void)
{
// This vector holds all the type structures
std::vector<ffi_type*> argumentTypes{ GetFFIType<Args>()... };
ffi_type * returnType = GetFFIType<Ret>();
// Rest of the code below
// ....
}
凡GetFFIType功能是通過以下實現的:
template <typename T>
ffi_type * GetFFIType(void)
{
// We will check for any kind of pointer types
if(std::is_pointer<T>::value || std::is_array<T>::value ||
std::is_reference<T>::value || std::is_function<T>::value)
return &ffi_type_pointer;
if(std::is_enum<T>::value)
//return GetFFIType<std::underlying_type<T>::type>();
{
// Since the size of the enum may vary, we will identify the size
if(sizeof(T) == ffi_type_schar.size) return std::is_unsigned<T>::value ? &ffi_type_uchar : &ffi_type_schar;
if(sizeof(T) == ffi_type_sshort.size) return std::is_unsigned<T>::value ? &ffi_type_ushort : &ffi_type_sshort;
if(sizeof(T) == ffi_type_sint.size) return std::is_unsigned<T>::value ? &ffi_type_uint : &ffi_type_sint;
if(sizeof(T) == ffi_type_slong.size) return std::is_unsigned<T>::value ? &ffi_type_ulong : &ffi_type_slong;
}
assert(false && "cannot identify type");
}
// These are all of our specializations
template <> ffi_type * GetFFIType<void>(void) { return &ffi_type_void; }
template <> ffi_type * GetFFIType<byte>(void) { return &ffi_type_uchar; }
template <> ffi_type * GetFFIType<char>(void) { return &ffi_type_schar; }
template <> ffi_type * GetFFIType<ushort>(void) { return &ffi_type_ushort; }
template <> ffi_type * GetFFIType<short>(void) { return &ffi_type_sshort; }
template <> ffi_type * GetFFIType<uint>(void) { return &ffi_type_uint; }
template <> ffi_type * GetFFIType<int>(void) { return &ffi_type_sint; }
template <> ffi_type * GetFFIType<ulong>(void) { return &ffi_type_ulong; }
template <> ffi_type * GetFFIType<long>(void) { return &ffi_type_slong; }
template <> ffi_type * GetFFIType<float>(void) { return &ffi_type_float; }
template <> ffi_type * GetFFIType<double>(void) { return &ffi_type_double; }
template <> ffi_type * GetFFIType<long double>(void) { return &ffi_type_longdouble; }
這個工作,但顯然有一些改進的餘地。如果類型無效(即類或結構),則在編譯時不會識別(發生運行時錯誤,而不是使用assert
)。我將如何避免這種情況,並使編譯過程中該函數確定類型是否有效(基本類型)?
我也不喜歡我在enum
的情況下識別底層類型的方式。我寧願用std::underlying_type<T>
代替(代碼中的註釋),但如果類型是例如一個空指針會發出編譯錯誤(type_traits:1762:38: error: ‘void*’ is not an enumeration type
)
我試圖實現使用std::enable_if
但沒有成功這種行爲...操作告訴我是否應該解釋一些事情,以防聽起來有點模糊!
摘要:我想要得到的GetFFIType功能在編譯期間決定一切,功能應該只支持基本類型(見this更爲詳盡的參考)
編輯:很抱歉的標題,沒有什麼更好的來介意:(
等等,第一次嘗試並不好。 'declval'會被評估。固定,我想。 – aschepler 2012-07-09 16:37:15