一些樣板:
namespace details {
template<template<class...>class, class, class...>
struct can_apply:std::false_type{};
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<template<class...>class Z, class... Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
} templateclass Z,類... TS> 使用can_apply =細節:: can_apply; 一個特徵,以確定是否應*
:
template<class T>
using unary_star_r = decltype(*std::declval<T>());
template<class T>
using can_unary_star = can_apply<unary_star_r, T>;
dispatch
在編譯的時候把他們之間的兩個參數和選秀權:
template<bool /*false*/>
struct dispatch_t {
template<class T, class F>
F operator()(T, F f)const{ return std::move(f); }
};
template<>
struct dispatch_t<true> {
template<class T, class F>
T operator()(T t, F)const{ return std::move(t); }
};
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__))\
->decltype(__VA_ARGS__)\
{ return __VA_ARGS__; }
template<bool b, class T, class F>
auto
dispatch(T t, F f)
RETURNS(dispatch_t<b>{}(std::move(t), std::move(f)))
我們幾乎完成了...
現在我們的工作。我們寫這代表解引用類型,什麼都不做,也許做任何函數對象:
struct maybe_deref_t;
struct do_deref_t;
struct identity_t {
template<class T>
T operator()(T&& t)const { return std::forward<T>(t); }
};
struct do_deref_t {
template<class T>
auto operator()(T&& t)const
RETURNS(maybe_deref_t{}(*std::forward<T>(t)))
};
這裏的工作:
struct maybe_deref_t {
template<class T>
auto operator()(T&& t)const
RETURNS(
dispatch< can_unary_star<T>::value >(
do_deref_t{},
identity_t{}
)(
std::forward<T>(t)
)
)
};
和更好的語法幫助:
template<class T>
auto maybe_deref(T&& t)
RETURNS(maybe_deref_t{}(std::forward<T>(t)))
測試代碼:
int main() {
auto bob = new int*(new int(7)); // or 0 or whatever
std::cout << maybe_deref(bob) << "\n";
}
live example。
我最初是用C++ 14風格編寫的,然後將它翻譯回C++ 11。在C++ 14中它更清潔。
不能你寫使用['標準:: is_pointer'(HTTP一個_type traits_基於遞歸模板:// en.cppreference.com/w/cpp/types/is_pointer)還是這樣? – user0042
@ user0042'std :: is_pointer'struct只會檢查'T'是否是*指針*,而不是迭代器,智能指針等。 –
您是否在尋找[std :: invoke](http:// en .cppreference.com /瓦特/ CPP /實用程序/功能/調用)? –