如何在具有不同模板参数的c++模板之间隐式强制转换
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
这可以工作,因为模板实参演绎不会隐式转换实参类型。例如float to 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;
}
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- 在cuda线程之间共享大量常量数据
- 在c代码之间共享数据的最佳方式
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 大小相等但成员数量不同的结构之间的性能差异
- 类与私有变量的其他类之间的线程安全性
- 如何在cpp文件之间切换窗口?在Qt中
- 线程之间的布尔停止信号
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 构造函数和转换运算符之间的重载解析
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数