| 網(wǎng)站首頁(yè) | 關(guān)于我們 | 開(kāi)發(fā)優(yōu)勢(shì) | 產(chǎn)品展示 |
| 合作企業(yè) | 新聞動(dòng)態(tài) | 聯(lián)系我們 | 電話聯(lián)系 |
文章作者:濟(jì)南軟件開(kāi)發(fā) 時(shí)間:2016年12月20日
獲取函數(shù)或成員函數(shù)的返回類(lèi)型,參數(shù)類(lèi)型,參數(shù)長(zhǎng)度,類(lèi)類(lèi)型。
函數(shù)參數(shù)列表推斷基于typelist:http://www.cnblogs.com/flytrace/p/3551414.html
先看一個(gè)普通函數(shù)非const的特化:
復(fù)制代碼
template<typename R, typename... Args>
struct function_traits<R (Args...)>
{
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
復(fù)制代碼
使用:
復(fù)制代碼
int testfunc1(char) { return 1; }
int main()
{
bool b;
b = std::is_same< typename function_traits<int(double)>::return_type, int>::value;
std::cout << "is same: " << b << std::endl;
b = std::is_same< typename function_traits<decltype(testfunc1)>::arg<0>::type, char>::value;
std::cout << "is same: " << b << std::endl;
}
復(fù)制代碼
對(duì)于各種參數(shù)類(lèi)型的普通函數(shù),都能正確推斷。但重載函數(shù)的情形需要我們考慮。如下我們?cè)黾觮estfunc1的重載版本:
bool testfunc1(double, char) { return false; }
此時(shí)decltype(testfunc1)是無(wú)法編譯通過(guò)的。這并不是我們的function_traits有問(wèn)題。而是在沒(méi)信息的情況下,decltype是無(wú)法選擇testfunc1的重載版本的。除非我們?cè)趂unction_traits顯式特化。
函數(shù)指針的function_traits也會(huì)遇到重載問(wèn)題,如下是針對(duì)函數(shù)指針的function_traits:
復(fù)制代碼
template<typename R, typename... Args>
struct function_traits<R (*)(Args...)>
{
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
復(fù)制代碼
decltye(&testfunc1)也是無(wú)法編譯通過(guò)的。很顯然,你自己作為編譯器作者的話,若是沒(méi)有額外的信息,讓你使用decltype去推斷一個(gè)可重載的函數(shù)類(lèi)型,你怎么能夠知道用戶(hù)希望得到哪個(gè)類(lèi)型?除了顯示特化以提供給編譯器信息外,對(duì)于函數(shù)指針,我們還可以提前轉(zhuǎn)換,顯式給以類(lèi)型信息供編譯器推斷,如下:
int (*castfunc)(char) = &testfunc1;
b = std::is_same< typename function_traits<decltype(castfunc)>::arg<0>::type, char>::value;
std::cout << "is same: " << b << std::endl;
castfunc1在定義時(shí)得到了testfunc1正確的重載類(lèi)型,因此decltype在推斷castfunc時(shí)就有了信息來(lái)選擇正確的類(lèi)型。
這并不是一個(gè)程序技術(shù)問(wèn)題,更算是一個(gè)邏輯問(wèn)題,就好像面對(duì)有多個(gè)定義的單詞,沒(méi)有上下文你是無(wú)法知道它要代表什么意思的。
這種顯示轉(zhuǎn)換并不會(huì)帶給我們太多困擾。因?yàn)槭褂胒unction_traits的場(chǎng)景,基本上是一種延遲推斷手段。比如得到消息后,使用泛型手法分發(fā)消息處理。而消息處理函數(shù)我們?cè)谧?cè)的時(shí)候肯定是知道函數(shù)類(lèi)型的,在注冊(cè)時(shí)我們就已經(jīng)可以顯示轉(zhuǎn)換這個(gè)函數(shù)指針而不會(huì)遇到重載問(wèn)題了。直接使用decltype(testfunc1)好像在我們測(cè)試function_traits時(shí)才會(huì)遇到,嗯,另一個(gè)人也遇到了,不然我不會(huì)試驗(yàn)。。。
然而確實(shí)存在一個(gè)可能,使我們可以傳入testfunc1,而不用給予完整類(lèi)型信息,雖然不適用于function_traits的情況。如下:
http://stackoverflow.com/questions/9054703/overloaded-function-as-argument-of-variadic-template-function
復(fù)制代碼
template<typename ...Args>
struct OverloadResolved
{
template<typename R>
static auto static_doit( R (*f) (Args...), Args ... args ) -> R { return f(args...);}
};
template<typename ...Args>
auto deduce(Args...) -> OverloadResolved<Args...> { return OverloadResolved<Args...>(); }
template<typename T>
struct dummy : public T { };
#define doit(f, ...) ( dummy<decltype(deduce( __VA_ARGS__ ))> :: static_doit(f, __VA_ARGS__) )
復(fù)制代碼
使用:
char aa = 'a'; double ff = 0.1;
std::cout << doit(testfunc1, aa) << " " << doit(testfunc1, ff, aa) << std::endl;
可以看到,雖然testfunc1有2個(gè)重載版本,但仍能正確的執(zhí)行testfunc1(aa)和testfunc1(ff, aa).
當(dāng)然因?yàn)榇颂幗o出了參數(shù)信息。這是一個(gè)運(yùn)行時(shí)方案,而function_traits要求我們?cè)诰幾g期就推斷。
以下添加類(lèi)成員函數(shù)的function_traits:
復(fù)制代碼
template <typename R, typename T, typename... Args>
struct function_traits<R (T::*)(Args...)>
{
typedef T class_type;
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
復(fù)制代碼
還需要添加const,volatile修飾符的。以下是更完整的版本:
template<typename T>
struct function_traits;
template<typename R, typename... Args>
struct function_traits<R (Args...)>
{
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template<typename R, typename... Args>
struct function_traits<R (Args...) const>
{
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template<typename R, typename... Args>
struct function_traits<R (Args...) volatile>
{
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template<typename R, typename... Args>
struct function_traits<R (Args...) const volatile>
{
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template<typename R, typename... Args>
struct function_traits<R (*)(Args...)>
{
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template <typename R, typename T, typename... Args>
struct function_traits<R (T::*)(Args...)>
{
typedef T class_type;
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template <typename R, typename T, typename... Args>
struct function_traits<R (T::*)(Args...) const>
{
typedef T class_type;
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template <typename R, typename T, typename... Args>
struct function_traits<R (T::*)(Args...) volatile>
{
typedef T class_type;
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
template <typename R, typename T, typename... Args>
struct function_traits<R (T::*)(Args...) const volatile>
{
typedef T class_type;
typedef R return_type;
typedef typelist<Args...> arglist;
enum { arg_count = sizeof...(Args) };
template<unsigned int N>
struct arg
{
typedef typename at<N, arglist>::type type;
};
};
想要了解更多詳情歡迎來(lái)電咨詢(xún)18678812288
登陸網(wǎng)址:m.h6244.cn。
聯(lián)系人:王經(jīng)理。