在编译时能以某种方式反映函数参数的类型吗?
那样
int b = add(3, 6)
将导致
形式的模板实例化int add(int a, int b) { return a + b }
从一些已声明的功能模板中
A add(A a, B b) { return a + b }
我不知道是否可以使用模板,它们似乎并不适用于繁重的元编程。
答案 0 :(得分:3)
template<typename T>
T add(T a, T b) { return a + b; }
然后你可以使用任何内置类型(int,short,double,float等)调用它,并根据你使用的类型在编译时实例化函数add
。
请注意,如果将其拆分为标题/来源,则会遇到问题:
add.h:
template<typename T>
T add(T a, T b);
add.cpp:
template<typename T>
T add(T a, T b) { return a + b; }
main.cpp中:
#include "add.h"
int a = 3;
int b = 5;
int i = add(a, b);
当您尝试编译它时,它将在链接时失败。这就是原因。
编译add.obj
使不实例化add
模板方法 - 因为它从未在add.cpp中调用过。编译main.obj
实例化函数声明 - 但不是函数体。因此,在链接时,它将无法找到add
方法的定义。
最简单的解决方法是将整个模板函数放在标题中:
add.h:
template<typename T>
T add(T a, T b) { return a + b; }
然后你甚至根本不需要add.cpp文件。
答案 1 :(得分:3)
这不是你要问的吗?
template <typename A, typename B>
A add(A a, B b) { return a + b; }
这不是“繁重的元编程”。
答案 2 :(得分:1)
这正是模板所做的事情。
template <typename T>
inline T add(T a, T b) { return a + b; }
允许两种不同的类型有点棘手,但也有可能。
答案 3 :(得分:1)
如果您计划使用除所需的简单类型之外的任何内容(在头文件中):
template <typename A>
inline A add(const A& a, const A& b) { return a + b; }
注意'内联'。
正如其他人所指出的,混合类型的问题是如何从参数类型确定返回类型。假设我们坚持使用简单类型并且具有:
模板 内联A添加(A a,B b){return a + b; }
然后失败(可能只有警告):
double d = add(1, 1.5); // Sets d to 2.0
所以你必须做一些工作。例如:
template<class A, class B>
struct Promote
{
};
template<class A>
struct Promote<A,A>
{
typedef A Type;
};
template<>
struct Promote<int, double>
{
typedef double Type;
};
template<>
struct Promote<double, int>
{
typedef double Type;
};
添加功能变为:
template<class A, class B>
inline typename Promote<A,B>::Type add(A a, B b)
{
return a + b;
}
所有这一切对您来说确保返回类型是您指定用于添加给定类型对的类型。这甚至适用于复杂类型。
答案 4 :(得分:0)
模板在编译时完成所有魔法,但这似乎足以满足您的要求:
template <class T>
T add(T a, T b) { return a + b; }
当两者可能不匹配时,它会变得更复杂,因此(例如)您可以向int
添加double
并获得double
结果。目前的标准并不真正支持 1 ;使用C ++ 0x,您可以查看auto
和decltype
来完成此类任务。
1 虽然Boost typeof
经常会这样做。