作者poyenc (髮箍)
看板C_and_CPP
標題Re: [問題] 如何消除泛型降轉的警告
時間Wed Aug 28 18:04:24 2019
※ 引述《s4300026 (s4300026)》之銘言:
: 開發平台(Platform): (Ex: Win10, Linux, ...)
: win7
: 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
: vc2010
: 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
: 問題(Question):
: 如題
: 餵入的資料(Input):
: T = Point, K = float
: T = PointF, K = double
: 預期的正確結果(Expected Output):
: 錯誤結果(Wrong Output):
: warning C4244
: 將 float 轉 int 可能導致資料遺失
: 將 double 轉 float 可能導致資料遺失
: 程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔)
: template <typename T, typename K>
: void func(T a, K b, T &c)
: {
: c.X = a.X * b;
: }
: 補充說明(Supplement):
: 原本以為 decltype 可以幫上忙, 但似乎不能這樣寫...
: c.X = (decltype c.X) (a.X * b);
: 正確寫法
: c.X = (decltype (c.X)) (a.X * b);
: 看到 warning 很煩躁...
: 我知道T, K不能亂丟型態進去
: 因此我想要把泛型做成 class private
: 然後 public 指定的T K
: 感謝大大撥冗觀看
在 C++98 裡通常是請 Point 提供 X 的型別給你, 即在類別裡提供
member types, 通常這樣可以避免不必要的 implicit conversion,
更換實作容易, 且對 client side 程式碼衝擊較小
struct Point {
using XType =
int;
XType X;
};
template <
typename T,
typename K>
void func(T a, K b, T &c)
{
c.X =
static_cast<
typename T::XType>(a.X * b);
}
因為這樣對型別的 constraint 加大了, 在 C++11 裡面雖然可以用
decltype 取得 X 的型別, 不過
需要注意運算子的引數為何, 一般
建議使用 T::X 加上 std::decay 拿到不含 & 的型別
struct Point {
int X;
};
template <
typename T,
typename K>
void func(T a, K b, T &c)
{
using XType =
typename std::decay<
decltype(
T::X)>::type;
c.X =
static_cast<XType>(a.X * b);
}
不過因為這個模版實在太泛用了, 導致阿貓阿狗都有可能被編譯器
丟進來嘗試具現化. 建議幫它加上一些 constraints, 這裡用的是
簡化版的 detection idiom
範例:
https://wandbox.org/permlink/OLxNtrWosKLv9NQI
--
P1389R0: Guidelines for Teaching C++ to Beginners
https://bit.ly/2GvDWKb
SG20 Education and Recommended Videos for Teaching C++
https://www.cjdb.com.au/sg20-and-videos
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.193.76.216 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1566986668.A.21E.html
※ 編輯: poyenc (123.193.76.216 臺灣), 08/28/2019 18:05:35
推 s4300026: 那個 ... 我的 Point, PointF 是 Clr 的 WinForm 結構.. 08/28 22:13
推 s4300026: 所以沒辦法定義型別 08/28 22:17
→ s4300026: 至於func(T a, K b, T &c) -> 的箭頭有看過一兩次 08/28 22:17
→ s4300026: 但目前完全沒搞動那個是做什麼用的 08/28 22:18
→ s4300026: 至於 template <typename...> using void_t = void; 08/28 22:18
→ s4300026: 則是連看都沒看過... 08/28 22:21
→ loveme00835: 關鍵字: trailing return type, variadic template 08/28 22:25
推 s4300026: 不過還是謝謝你的回答 08/28 22:25
→ loveme00835: 和 decltype 一樣都是 C++11 加入的 feature, 最後的 08/28 22:25
→ loveme00835: 概念是 SFINAE (substitution failure is not an 08/28 22:26
→ loveme00835: error) 08/28 22:26
→ s4300026: mouth-cannon-auto 08/29 09:04