[英]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.