2010-06-24 34 views
1

我想用C++模板创建一个简单的整数范围检查器和转换器。
的代码看起来是这样的:C++中的安全整数转换

// D is the "destination" type and S the "source" type 
template <class D, class S> 
inline D SafeConvert(S value); 

template <class S> 
inline int SafeConvert<int>(S value) { 

    ASSERT(value >= S(INT_MIN) && value <= S(INT_MAX)); 
    return int(value); 
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments 


template <class S> 
inline size_t SafeConvert<size_t>(S value) { 

    ASSERT(value >= S(0) && value <= S(size_t(-1))); 
    return size_t(value); 
} /// error C2768: 'SafeConvert' : illegal use of explicit template arguments 


// ... 

void test() { 

    size_t v = INT_MAX+1; 
    int iv = SafeConvert<int>(v); 
} 

不过,我有以下来编译错误:

error C2768: 'SafeConvert' : illegal use of explicit template arguments 

我的问题是如何告诉我要专注只有d类的编译器?

谢谢。

+0

你可能想尝试http://stackoverflow.com/questions/998571/c-template-for-safe-integer-casts/998982#998982 – 2010-06-26 15:17:46

回答

5

不能部分专门函数模板:

后者可以实现如下。你需要用类包装器来模拟它,或者使用标准函数重载。 mimicing的例子:

template <typename T1, typename T2> 
struct processor; 

template < typename T1, typename T2 > 
T1 fun(T2 t2) { return processor<T1,T2>::apply(t2); } 

template < typename T2 > 
struct processor<int,T2> 
{ 
    static int apply(T2 t2) { .... } 
}; 

...etc... 
+0

或者只是使用一个库。 – 2010-06-24 16:41:18

1

编写一个结构SafeConverter<T, S>用于SafeConvert。比部分专业化更好的是使用std::numeric_limits,或者甚至是boost::numeric_cast,它已经以更复杂的方式实现了范围检查。

template<typename T, typename S> 
struct numeric_converter { 
    static T convert(const S& val); 
} 
template<typename T, typename S> 
T numeric_cast(const S& val) { 
    typedef numeric_converter<T, S> converter; 
    return converter::convert(val); 
} 
+1

我不会否定,因为我几乎说同样的事情,但你应该先检查你的答案。那么你可能会想起为什么你不能这样做。 – 2010-06-24 16:04:50

+0

与SO的问题是,答案弹出方式太快,所以我通常没有时间在发帖之前思考我的答案,抱歉。 – Philipp 2010-06-24 16:10:30

0

只要写SafeConvert<size_t, S>而不是SafeConvert<size_t>,我认为,只有专业的第二个参数。 Noah Roberts在功能和类型的部分专业化方面也是正确的。

+0

其他方法,你想专门化第一个(目标)参数。 – 2010-06-24 16:23:54

+0

@Mike:谢谢,修正。 – 2010-06-24 21:19:35

4

这将是一个麻烦,地狱来维护。

通常我会建议使用numeric_limits

template <class D, class S> 
D SafeConvert(S value) 
{ 
    ASSERT(value >= std::numeric_limits<D>::min() 
     && value <= std::numeric_limits<D>::max()); 
    return static_cast<D>(value); 
} 

但是有每当你比较一个无符号的一个符号整数编译器发出一个警告...(从来没有真正的方式理解这一点)

因此,我建议使用Boost.NumericConversion,而不是重新发明轮子,特别是:boost::numeric_cast<>

当不需要检查(即目标类型大于源类型)并且以其他方式执行必要的检查时,它将保证性能免费。

+0

数字限制和boost :: numeric_cast是要走的路。 – Puppy 2010-06-24 21:23:09

+0

在S的最大值和D的最大值较大的情况下,这是否表明工作正常?或者将隐式转换将其向一个方向拧紧? – 2012-07-29 17:56:11

+0

@JosephGarvin:我非常确信'boost :: numeric_cast'可以工作;)对于这里介绍的自定义解决方案,恐怕我不知道内心的转换。 – 2012-07-30 07:07:11