我在http://codepad.org/ko8vVCDF编写了一个使用模板函数的示例程序。
如何将模板功能限制为仅使用数字? (int,double等。)
#include <vector>
#include <iostream>
using namespace std;
template <typename T>
T sum(vector<T>& a)
{
T result = 0;
int size = a.size();
for(int i = 0; i < size; i++)
{
result += a[i];
}
return result;
}
int main()
{
vector<int> int_values;
int_values.push_back(2);
int_values.push_back(3);
cout << "Integer: " << sum(int_values) << endl;
vector<double> double_values;
double_values.push_back(1.5);
double_values.push_back(2.1);
cout << "Double: " << sum(double_values);
return 0;
}
答案 0 :(得分:20)
这可以通过使用SFINAE来实现,并且通过使用Boost或C ++ 11中的帮助程序变得更容易
升压:
#include <vector>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
template<typename T>
typename boost::enable_if<typename boost::is_arithmetic<T>::type, T>::type
sum(const std::vector<T>& vec)
{
typedef typename std::vector<T>::size_type size_type;
T result;
size_type size = vec.size();
for(size_type i = 0; i < size; i++)
{
result += vec[i];
}
return result;
}
C ++ 11:
#include <vector>
#include <type_traits>
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, T>::type
sum(const std::vector<T>& vec)
{
T result;
for (auto item : vec)
result += item;
return result;
}
答案 1 :(得分:19)
您可以这样做:
template <class T>
class NumbersOnly
{
private:
void ValidateType( int &i ) const {}
void ValidateType( long &l ) const {}
void ValidateType( double &d ) const {}
void ValidateType( float &f ) const {}
public:
NumbersOnly()
{
T valid;
ValidateType( valid );
};
};
如果您尝试创建没有ValidateType重载的NumbersOnly,则会收到错误:
NumbersOnly<int> justFine;
NumbersOnly<SomeClass> noDeal;
答案 2 :(得分:18)
限制模板的唯一方法是使它使用所需类型的东西,而不是其他类型的东西。
因此,使用int构造,使用+和+ =,调用复制构造函数等。
任何具有所有这些功能的类型都可以使用你的功能 - 所以,如果我创建一个具有这些功能的新类型,你的功能将会起作用 - 这很棒,不是吗?
如果您想进一步限制它,请使用仅为您想要的类型定义的更多功能。
实现此目的的另一种方法是创建一个特征模板 - 类似这样的
template<class T>
SumTraits
{
public:
const static bool canUseSum = false;
}
然后将它专门用于你想要的课程:
template<>
class SumTraits<int>
{
public:
const static bool canUseSum = true;
};
然后在你的代码中,你可以写
if (!SumTraits<T>::canUseSum) {
// throw something here
}
编辑:如评论中所述,您可以使用BOOST_STATIC_ASSERT使其成为编译时检查而不是运行时检查
答案 3 :(得分:3)
你就是这样做的。
注意double的模板特化,例如..它不允许你用double作为参数调用该函数。诀窍在于,如果你尝试使用不属于IsNumber
特化的类型调用sum,则调用泛型实现,并且该实现使得不允许的内容(调用私有构造函数)。
除非您将IsNumber
类重命名为听起来像错误消息的内容,否则错误消息不直观。
#include <vector>
#include <iostream>
using namespace std;
template<class T> struct IsNumber{
private:
IsNumber(){}
};
template<> struct IsNumber<float>{
IsNumber(){};
};
template<> struct IsNumber<double>{
IsNumber(){};
};
template<> struct IsNumber<int>{
IsNumber(){};
};
template <typename T>
T sum(vector<T>& a)
{
IsNumber<T> test;
T result = 0;
int size = a.size();
for(int i = 0; i < size; i++)
{
result += a[i];
}
return result;
}
int main()
{
vector<int> int_values;
int_values.push_back(2);
int_values.push_back(3);
cout << "Integer: " << sum(int_values) << endl;
vector<double> double_values;
double_values.push_back(1.5);
double_values.push_back(2.1);
cout << "Double: " << sum(double_values);
return 0;
}
答案 4 :(得分:1)
为什么要在这种情况下限制类型?模板允许“静态鸭子输入”,因此在这种情况下允许sum
函数允许的任何内容。具体来说,T
所需的唯一操作是添加分配和初始化为0,因此支持这两个操作的任何类型都可以工作。这就是模板之美。
(如果您将初始化程序更改为T result = T();
之类,那么它也适用于数字和字符串。)
答案 5 :(得分:1)
您可以查看类型特征(使用boost,等待C ++ 0x或创建自己的特征)。
我在google上发现了以下内容:http://artins.org/ben/programming/mactechgrp-artin-cpp-type-traits.pdf
答案 6 :(得分:1)
确实,没有必要让它更严格。看一下字符串版本(使用Chris Jester-Young建议的默认构造函数样式)here ...
请注意溢出 - 您可能需要更大的类型来包含中间结果(或输出结果)。欢迎来到元编程领域,然后:)