读书人

模板参数推导有关问题

发布时间: 2012-02-10 21:27:42 作者: rapoo

模板参数推导问题
#include <cstdio>
#include <boost/lexical_cast.hpp>

template <typename T, T f> struct WapperFunction;

template <typename RetType, RetType (*f)()>
struct WapperFunction <RetType(*)(), f>
{
static void call()
{
RetType x = f();

printf( "Call result of 0X%p {%s} is %s {%s}\n\n ", f, typeid(f).name(),
boost::lexical_cast <std::string> (x).c_str(), typeid(x).name());
}
};

template <typename RetType, typename Arg1Type, RetType (*f)(Arg1Type)>
struct WapperFunction <RetType(*)(Arg1Type), f>
{
static void call()
{
Arg1Type arg1;
RetType ret;

printf( "Enter the argument1{%s}: ", typeid(Arg1Type).name());
std::cin> > arg1;

ret = f(arg1);

printf( "Call result of 0X%p {%s} is %s {%s}\n\n ", f, typeid(f).name(),
boost::lexical_cast <std::string> (ret).c_str(), typeid(ret).name());
}
};


int f1()
{
return 0;
}

int f2(int x)
{
return x * x;
}

int main()
{
WapperFunction <int(*)(), f1> ::call();
WapperFunction <int(*)(int), f2> ::call();
};

运行效果如:

Call result of 0X00441361 {int (__cdecl*)(void)} is 0 {int}

Enter the argument1{int}:23
Call result of 0X00441906 {int (__cdecl*)(int)} is 529 {int}

现在的问题是 WapperFunction <int(*)(int), f2> ::call(); 的调用中第一个模板参数 int(*)(int) 是可以从第二个参数 f2 中推导出来的。但应该如何使用才能让它进行推导? 使调用方式为:

WapperFunction <f1> ::call();
WapperFunction <f2> ::call();

或者有办法在运行期来生成全局函数的话,这种调用方式也可以:

WapperFunction::call(f1);
WapperFunction::call(f2);

注意生成的必须要是全局函数,不能是函数对象(需要和 C API 交互)。




[解决办法]
为什么不直接使用全局函数呢?

#include <cstdio>
#include <iostream>
#include <boost/lexical_cast.hpp>

template <typename RetType>
void call(RetType(*f)())
{
RetType x = f();

printf( "Call result of 0X%p {%s} is %s {%s}\n\n ", f, typeid(f).name(),
boost::lexical_cast <std::string> (x).c_str(), typeid(x).name());
}

template <typename RetType, typename Arg1Type>
static void call(RetType(*f)(Arg1Type))
{
Arg1Type arg1;
RetType ret;

printf( "Enter the argument1{%s}: ", typeid(Arg1Type).name());
std::cin> > arg1;

ret = f(arg1);

printf( "Call result of 0X%p {%s} is %s {%s}\n\n ", f, typeid(f).name(),
boost::lexical_cast <std::string> (ret).c_str(), typeid(ret).name());
}

int f1()
{
return 0;
}

int f2(int x)
{
return x * x;
}

int main()
{
call(&f1);
call(&f2);
}
------解决方案--------------------


哦,一开始没有完全领会,不好意思。

那是有点麻烦了,你需要的是void(*)(void),于是甭指望依靠函数参数了;
而C++中,能进行推导的只有函数模板,类模板不行的。那函数靠什么来推导参数?当然只有靠函数参数。
——矛盾出来了。:(

偶还是继续关注吧。:(
[解决办法]
template <typename RetType>
struct WapperFunction
{
typedef RetType (*FUNC)();
static void call()
{
RetType x = f_();

printf( "Call result of 0X%p {%s} is %s {%s}\n\n ", f_, typeid(f_).name(),
boost::lexical_cast <std::string> (x).c_str(), typeid(x).name());
}
static FUNC f_;
};

template <typename RetType>
typename WapperFunction <RetType> ::FUNC WapperFunction <RetType> ::f_;

template <typename RetType>
void (*Call(RetType (*f)()))()
{
WapperFunction <RetType> ::f_ = f;
return WapperFunction <RetType> ::call;
}

int f1()
{
return 0;
}

int main()
{
Call(f1)();
system( "pause ");
return 0;

}
[解决办法]
嗯,也有道理。

但我觉得类型萃取一般是指从一个类型参数推导出一些跟它相关的类型。但你这里当把f传给模板时,它却是作为一个常量参数,而不是类型参数。

而对于常量参数,在编译期它的一切都是已知的,从来不需要推导什么。

但如果不考虑常量参数,那就更没折了:“萃取”当然需要有原材料,换句话说,你还是得在那个模板类实例化时,在那对尖括号中写点东西(类型参数),否则依据谁来萃取?

以上个人想法,可能不够严密。
[解决办法]
不知道是不是要这种效果(请先看main中):
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
template <typename RetType,
typename Arg1Type,
typename Arg2Type,
typename Arg3Type,
typename Arg4Type,
typename Arg5Type>
void call (RetType* f,Arg1Type arg1,
Arg2Type arg2,
Arg3Type arg3,
Arg4Type arg4,
Arg5Type arg5)
{
(*f)(arg1,arg2,arg3,arg4,arg5);
};
///////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
template <typename RetType, typename Arg1Type>
void call (RetType* f,Arg1Type arg1)
{
(*f)(arg1);
};
/////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
int f1()
{
return 0;
}

int f2(int x)
{
printf( "x:%d\n ",x);
return x * x;
}
int f3(double x)
{
printf( "dx:%lf\n ",x);
return x * x;
}

double f4(double x1,double x2,double x3,double x4,double x5)
{
printf( "5dx:%lf,%lf,%lf,%lf,%lf\n ",x1,x2,x3,x4,x5);
return x1 + x2;
}

int main()
{
call(f2,100);
call(f3,10.02);
call(f4,1.1,2.2,3.3,4.4,5.5);
};



[解决办法]
基本搞定!
namespace {
template <typename RetType, typename COOKIE>
struct WapperFunction
{
typedef RetType (*FUNC)();
static void call()
{
RetType x = f_();
printf( "Call result of 0X%p {%s} is %s {%s}\n\n ", f_, typeid(f_).name(),
boost::lexical_cast <std::string> (x).c_str(), typeid(x).name());
}
static FUNC f_;
};

template <typename RetType, typename COOKIE>
typename WapperFunction <RetType, COOKIE> ::FUNC WapperFunction <RetType, COOKIE> ::f_;



template <typename RetType, typename COOKIE>
void (*Call(RetType (*f)(), COOKIE))()
{
WapperFunction <RetType, COOKIE> ::f_ = f;
return WapperFunction <RetType, COOKIE> ::call;
}
template <int line>
struct Helper_{};
}
#define CALL(f) Call(f, Helper_ <__LINE__> ())

读书人网 >C++

热点推荐