[英]c++ templates, how to map template parameters to other template parameters
[英]How to implicitly cast between C++ templates with different template parameters
我试图创建一个包装整数值的C ++模板类,并检查该值是否始终在有效范围内,因此简化的代码如下:
struct OutOfRangeError
{ };
template<int MIN, int MAX, typename TYPE>
struct IntegerRange
{
private:
TYPE mValue;
public:
IntegerRange(const TYPE value) : mValue(value)
{
if (MIN > value || value > MAX)
{
throw OutOfRangeError();
}
}
operator TYPE() const
{
return mValue;
}
}
以前的代码可以工作,但在使用这个类时它有一些缺点。 这是一个示例:
typedef IntegerRange<0, 4, int> range1_t;
typedef IntegerRange<0, 5, int> range2_t;
range1_t a = 3;
//range2_t b = a; // This does not work
range2_t b = static_cast<int>(a); // This works OK
因此,要在不同范围之间分配值,我必须明确地转换为给定的TYPE。 我想有一个解决方案,以避免这种显式转换和处理IntegerRange类,因为它们是正常的整数。 所以开发人员应该感觉他正在处理普通的整数而不是类。
为了解决这个问题,我试了不同的东 一个工作是以下一个作为额外的构造函数:
template<typename RANGE_TYPE>
IntegerRange(const RANGE_TYPE &value) :
mValue(static_cast<const TYPE>(value))
{
if (MIN > mValue || mValue > MAX)
{
throw OutOfRangeError();
}
}
但是,即使这样可行,我也不太喜欢,因为RANGE_TYPE可以是任何能够转换为TYPE的类型,我想将此限制为只有IntegerRange类。 要仅将其限制为IntegerRange类,我尝试了以下但是它没有编译,我不明白原因:
template<int ARG_MIN, int ARG_MAX, typename ARG_TYPE>
IntegerRange(const IntegerRange<ARG_MIN, ARG_MAX, typename ARG_TYPE> &value) :
mValue(static_cast<const TYPE>(value))
{
if (MIN > value || value > MAX)
{
throw OutOfRangeError();
}
}
问题是2:
*为什么最后一段代码没有编译,我需要更改以编译它。
*有没有更好的避免我遗漏的明确演员?
谢谢
首先, 您不应该使用ARG_MAX
作为模板名称,因为它可能已经被定义为POSIX数字常量。
其次,您应该删除IntegerRange
的第三个模板参数中的typename
:
IntegerRange(const IntegerRange<ARG_MIN, ARG_MAX, ARG_TYPE> &value) :
也许您应该将value
为ARG_TYPE
,它将直接调用您的operator ARG_TYPE()
,然后让编译器从ARG_TYPE
转换为TYPE
而不是转换为TYPE
并让编译器推断从ARG_TYPE
可能的转换和对operator ARG_TYPE()
的调用。 使用第一种解决方案,有关不可能转换的编译错误可能更明确。
RANGE_TYPE可以是任何能够转换为TYPE的类型,我想将其限制为只有IntegerRange类。 仅限于IntegerRange
只需交换模板参数的顺序并声明为
template<typename TYPE, TYPE2 MIN, TYPE2 MAX>
struct IntegerRange
这将起作用,因为模板参数推导不会隐式转换arg类型。 例如float到int。
//range2_t b = a; // This does not work
当然。 a
和b
有不同的类型。 请记住,对于每个模板专业化,都会创建该类的新模板。 您不能分配两个对象,因为它们的类型看起来相似。
class A { int a; }; class B { int a; };
A a; B b; a = b; // Should not work
为了做a = b
你需要提供可以从另一个IntegerRange
构造IntegerRange
复制构造函数。 (这里不需要赋值,因为你有类型转换运算符。)
template<typename TYPE2, TYPE MIN2, TYPE MAX2>
IntegerRange(const IntegerRange<TYPE2,MIN2,MAX2>& ot) {
if (MIN > ot.mValue || ot.mValue > MAX)
{
throw OutOfRangeError();
}
mValue = ot.mValue;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.