作者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://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1566986668.A.21E.html
※ 编辑: poyenc (123.193.76.216 台湾), 08/28/2019 18:05:35
1F:推 s4300026: 那个 ... 我的 Point, PointF 是 Clr 的 WinForm 结构.. 08/28 22:13
2F:推 s4300026: 所以没办法定义型别 08/28 22:17
3F:→ s4300026: 至於func(T a, K b, T &c) -> 的箭头有看过一两次 08/28 22:17
4F:→ s4300026: 但目前完全没搞动那个是做什麽用的 08/28 22:18
5F:→ s4300026: 至於 template <typename...> using void_t = void; 08/28 22:18
6F:→ s4300026: 则是连看都没看过... 08/28 22:21
7F:→ loveme00835: 关键字: trailing return type, variadic template 08/28 22:25
8F:推 s4300026: 不过还是谢谢你的回答 08/28 22:25
9F:→ loveme00835: 和 decltype 一样都是 C++11 加入的 feature, 最後的 08/28 22:25
10F:→ loveme00835: 概念是 SFINAE (substitution failure is not an 08/28 22:26
11F:→ loveme00835: error) 08/28 22:26
13F:→ s4300026: mouth-cannon-auto 08/29 09:04