你可以用SFINAE和一些特徵類來做到這一點。
我懷疑做到這一點的最好方法是期待一個兼容通話的仿函數 - 這也會更容易。
#include <utility>
#include <type_traits>
template<typename T, bool=true>
struct raw_write_compatible: std::false_type {};
template<typename T, bool=true>
struct raw_read_compatible: std::false_type {};
template<typename T>
struct raw_write_compatible<
T,
std::is_convertable<
decltype(
std::declval<T&>()(
std::declval<uint8_t *>(),
std::declval<size_t>()
)
),
int
>::value
>: std::true_type {};
template<typename T>
struct raw_read_compatible<
T,
std::is_convertable<
decltype(
std::declval<T&>()(
std::declval<uint8_t *>(),
std::declval<size_t>()
)
),
int
>::value
>: std::true_type {};
的這些要點是raw_read_compatible<T>::value
是true
IFF的T
一個實例可以通過與簽名(uint8_t*, size_t)
進行評估,並返回類型可以轉換爲一個int
。
(順便說一句,你的「寫」函數簽名或許應該採取指針const uint8_t
,因爲它不修改參數。)
你會使用這樣的:
template<typename Reader, typename Writer>
typename std::enable_if<
raw_read_compatible<Reader>::value && raw_write_compatible<Writer>::value,
bool // return value of do_some_io_stuff
>::type do_some_io_stuff(Reader const& reader, Writer const& writer) {
return true;
}
和do_some_io_stuff
將匹配iff讀寫器可以以您想要的方式調用。
這樣做的好處,當你試圖在不兼容的拉姆達或函數指針或仿函數來傳遞do_some_io_stuff
未能比賽,而不是匹配,然後未能編譯。從理論上講,這可以讓你覆蓋事物。
上述解決方案需要一個具有良好C++ 11支持的編譯器:例如,MSVC2012不支持上述操作(它缺少「表達式SFINAE」)。
一個簡單的解決辦法是隻取std::function< int(uint8_t*, size_t) >
,但有兩項費用:第一,它在每次調用運行時間成本(大致相當於一個virtual
方法調用 - 相比IO時使不高) - 通過函數調用邊界阻止優化的實際成本。其次,你可以得到一些編譯失敗,而不是失敗,以符合我的經驗中的簽名錯誤(我不確定C++ 11標準是否指定std::function
的「lambda」構造函數只有在傳遞兼容類型時才匹配,但我認爲我已經看到那些測試失敗的實現)。
std::function
解決方案的優點是它更簡單,它允許將實現放在單獨的文件中,並且意圖更易於理解。
如果你只接受一個參數類型,它有什麼用途嗎? – 2013-05-10 14:41:01
@SanderDeDycker我自己有點困惑,但我*想*他想要一個類模板,它將保存一些可用指定簽名調用的對象。但它可能是一個函數指針,函子,lambda,只要它有正確的簽名。所以['std :: function'](http://en.cppreference.com/w/cpp/utility/functional/function)可能是某種形式的答案。 – BoBTFish 2013-05-10 14:43:22
@BoBTFish:看起來你是對的 - 也閱讀標題,而不僅僅是身體幫助:-) – 2013-05-10 14:48:44