有没有办法使用模板来避免缩小转换范围
Is there a way using templates to avoid narrowing conversion?
以下列例子为例:
#include <iostream>
#include <vector>
#include <type_traits>
template<typename T>struct X
{
std::vector<T> v;
void clear() { v.clear(); }
~X(){}
X(){ clear(); }
X(const X &x) { v=x.v; }
//template<typename ...I> X(I...i) : v({static_cast<T>(i)...}) {} //<---gets rid of warnings only, still narrowing
template<typename ...I> X(I...i) : v({i...}) {}
template<typename U> X(const U &u) { for (auto e:u.v) v.push_back((T)e); }
bool operator==(const X &x) const { return (v==x.v); }
template<typename U> bool operator==(const U &u) { X<T> x(u); return (v==x.v); }
void show(const std::string &s) const
{
using TYPE=typename std::common_type<T,int>::type;
std::cout << s << " = ";
for (auto x:v) std::cout << (TYPE)x << " ";
std::cout << "n";
}
};
template<typename T> bool testit(const T a, const T b)
{
return (a==b);
}
template<typename T> bool testit(const X<T> a, const X<T> b)
{
return (a==b);
}
template<typename T, typename U> bool testit(const X<T> a, const X<U> b)
{
X<T> c(b); // this is the problem - t=int, U=double => narrowing
return testit(a, c);
/*
// tried doesn't work
if (sizeof(decltype(T()))<sizeof(decltype(U())))
{
X<U> c(a);
X<U> d(b);
return testit(c,d);
}
else
{
X<T> c(a);
X<T> d(b);
return testit(c,d);
}
*/
/*
//doing the following causes a segfault -- I have no idea why
using T1=typename std::common_type<T, int>::type;
using T2=typename std::common_type<U, int>::type;
using TT=typename std::common_type<T1, T2>::type;
X<TT> c(a);
X<TT> d(b);
return testit(d,b);
*/
}
int main(int argc, const char *argv[])
{
auto res=[](bool b)->std::string{ return b?"OK":"Fail"; };
auto test=[res](const std::string s, bool btest, bool bexp){ std::cout << s << " - " << res(btest==bexp) << "n"; };
test("(1,1)", testit(1,1), 1);
test("(1,2)", testit(1,2), 0);
test("(abc,abc)", testit("abc","abc"), 1);
test("(abc,aaa)", testit("abc","aaa"), 0);
X<int> xa{1,2,3}; xa.show("xa");
X<double> xb{1.0, 2.0, 3.0}; xb.show("xb");
X<char> xc{2,4,6}; xc.show("xc");
X<double> xd{1.1, 2.1, 3.1}; xd.show("xd");
test("(xa, xb)", testit(xa,xb), 1);
test("(xa, xc)", testit(xa,xc), 0);
test("(xb, xc)", testit(xb,xc), 0);
test("(xc, {2.0, 4.0, 6.0})", testit(xc, {2.0, 4.0, 6.0}), 1);
test("(xc, {2.0, 4.1, 6.0})", testit(xc, {2.0, 4.1, 6.0}), 0);
test("(X<int>({4, 5, 6}), {4.0, 5.0, 6.0})", testit(X<int>({4, 5, 6}), {4.0, 5.0, 6.0}), 1);
test("(X<int>({4, 5, 6}), {4.0, 5.0, 6.1})", testit(X<int>({4, 5, 6}), {4.0, 5.0, 6.1}), 0);
return 0;
}
当 T 为 int 且 U 为双精度时,这会导致变窄。
由于我不知道模板参数在运行时的顺序,有没有办法避免这种缩小 - 以便将 int 转换为双精度 - 无论参数的顺序如何?
警告来自具有可变参数包的 X
的一个构造函数。您可以通过显式强制转换来使编译器静音:
template<typename ...I> X(I...i) : v({static_cast<T>(i)...}) {}
这摆脱了警告,比如说,X<char> xc{2,4,6};
,我认为你不介意缩小。
testit
内部构造X
时缩小,可以使用std::common_type
:
X< std::common_type_t<T,U> > c(b);
若要使警告静音,请显式执行强制转换:
template<typename ...I> X(I...i) : v({static_cast<T>(i)...}) {}
演示
相关文章:
- 奇怪的缩小转换在 g++ 编译器中加倍到浮点警告
- 如何在不强制转换每个参数的情况下删除初始值设定项列表中从 int 到 char 的缩小转换?
- 为什么显式构造被视为(隐式)缩小转换?
- 为什么C++在将浮点数转换为字符时没有显示缩小转换错误?
- 为什么 gcc 警告只针对统一初始化缩小转换范围?
- C++ - 从 "int" 到 "unsigned char" 的缩小转换无效
- gcc在 运算符中缩小转换
- 从'::size_t'转换为'int'需要缩小转换范围
- 列表初始化时需要缩小转换范围
- 从'double'转换为'int'需要缩小转换范围
- 从“ int”到'int16_t {aka short int}'内部{}的“((int)a) -1)”的缩小转换
- 为什么缩小转换范围不能防止错误类型的map.insert()失败
- 在Linux上构建Ogre时出错:缩小转换范围
- C++ / OpenGL:纹理到像素图示例 - 缩小转换误差
- 如何禁用Visual Studio警告C4244,用于std::vector复制或使用隐式缩小转换进行赋值
- 有没有办法使用模板来避免缩小转换范围
- 如果第二个属性未支撑,则将与支撑初始化器配对缩小转换
- 如何禁用缩小转换警告
- 警告缩小转换范围(uint32 到 uint8)
- 从'float'转换为'LONG'需要缩小转换范围