c++ - 是否可以避免最终不会运行的 c++ 模板函数的部分错误?
问题描述
我有一个带有两个整数作为输入的模板。一个可能比另一个有更大的类型。我的代码相应地进行了转换,因此结果适合目标类型。
下面是函数的基本思想:
template<typename S, typename D>
D convert(S a)
{
return static_cast<D>(a);
}
S
但是,当和之间的大小D
发生变化时,我想改变值。所以我添加了几个条件:
if(sizeof(S) < sizeof(D))
{
return a << (sizeof(D) - sizeof(S)) * 8;
}
if(sizeof(S) > sizeof(D))
{
return a >> (sizeof(S) - sizeof(D)) * 8;
}
问题是我收到这些错误:
Conversions.cpp:在 'void convert(buffer_&) [with S = unsigned char; D = 短无符号整数;buffer_t = std::vector]':
conversions.cpp:从这里需要
conversions.cpp:错误:右移计数 >= 类型的宽度 [-Werror=shift-count-overflow]d[idx] = convert_sign<S, D>(static_cast<std::int64_t>(s[idx]) >> (sizeof(S) - sizeof(D)) * 8);
_注意:对于那些不理解的人,错误块中的(sizeof(S) - sizeof(D))
or (sizeof(D) - sizeof(S))
when将是负数,因此被视为非常大的移位参数(由于移位参数被视为无符号值,它非常大而不是负数,无论如何返回a未签名。) if()
sizeof()
std::size_t
显然,我可以使用编译指示忽略警告并完成它。
不过,我所期望的是,if()
that hasfalse
不会被编译,所以不会有错误,因为那发生在编译时(即编译器知道该if()
块是否会在它被编译时被执行。)是有没有办法不使用编译指示并仍然避免错误?
解决方案
但是,我所期望的是,具有 false 的 if() 不会被编译,因此不会有错误,因为那发生在编译时(即编译器知道 if() 块是否将在它被编译的时间。)
不幸的是,您正在描述的行为if constexpr
只能从 C++17 开始
当你写
if constexpr ( some_compile_time_test )
some_code_1;
else
some_code_2;
wheresome_compile_time_test
是可以在编译时确定的测试(as sizeof(S) < sizeof(D)
),编译器编译some_code_1
- 并完全忽略some_code_2
- 当测试是true
,反之亦然,否则
如果你只写
if ( some_test )
some_code_1;
else
some_code_2;
如果测试some_test
是否是可推断的编译时间并不重要:编译器可以优化代码而忽略未使用的部分,但该部分必须是可编译的。
在 C++17 之前(主要但不仅是 C++11 和 C++14),您必须开发两个(或更多)不同的函数/方法。
寻找“SFINAE”和“标签调度”来查看一些有用的方法。
SFINAE 的一个例子
template <typename S, typename D>
typename std::enable_if<(sizeof(S)<sizeof(D)), S>::type convert (S a)
{ return a << (sizeof(D) - sizeof(S)) * 8; }
template <typename S, typename D>
typename std::enable_if<(sizeof(S)>sizeof(D)), S>::type convert (S a)
{ return a >> (sizeof(S) - sizeof(D)) * 8; }
和一个标签调度的例子(注意:代码未测试)
template <typename S, typename D>
S convert (S a, std::true_type)
{ return a << (sizeof(D) - sizeof(S)) * 8; }
template <typename S, typename D>
S convert (S a, std::false_type)
{ return a >> (sizeof(S) - sizeof(D)) * 8; }
template <typename S, typename D>
S convert (S a)
{ return convert<S, D>(a, std::integral_constant<bool, (sizeof(S)<sizeof(D))>{}); }
推荐阅读
- python - 如果下面的行重复,则使用其他列中的值,直到找到新值
- node.js - MongoDB在日期在表行的开始日期和结束日期之间时获取数据
- snowflake-cloud-data-platform - 如何在雪花中创建一个表,但防止在同一角色下删除它?
- python - 在类的加载方法中覆盖self
- c# - 使用泛型接口子类型解析类型
- javascript - 拿
作为整数
- python - 如果涉及 Inf,为什么稀疏矩阵的矩阵乘法与密集矩阵的乘法不同?
- java - spring-boot java中没有ssl客户端会话缓存
- jmeter - 在 JMeter 中使用 JSR223 后处理器检索请求数据信息
- javascript - 如何使用同步函数在节点 js 中获取目录的大小