为何common_type_t未生成预期通用类型?容器类型异常解析
问题:容器元素类型为何被认为是int而非从参数包推测的double?
请看以下代码:
#include <iostream> #include <vector> using namespace std; template<template <class ...> class Container, typename ... Args> Container<common_type_t<remove_cvref_t<Args> ...>> fn( Args &&... args ); int main() { for( int i : fn<vector>( 1, 2.6, 3 ) ) cout << i << ", " << endl; // 输出正确类型... cout << typeid(common_type_t<int, double>).name() << endl; } template<template <class ...> class Container, typename ... Args> Container<common_type_t<remove_cvref_t<Args> ...>> fn( Args &&... args ) { Container<common_type_t<remove_cvref_t<Args> ...>> cont; (cont.emplace_back( forward<Args>( args ) ), ...); return cont; }
编译器对fn<>()的函数调用给出如下警告:
'initializing': conversion from '_Ty' to 'int', possible loss of data
原因解析
你误解了问题的根源:容器的元素类型实际上是double,而非int。
问题出在main函数的范围for循环里:
for( int i : fn<vector>( 1, 2.6, 3 ) )
这里的int i是你显式声明的循环变量类型,编译器需要把容器中存储的double类型元素转换为int,这才触发了“可能丢失数据”的警告。
验证这一点很简单:把循环变量类型改成auto或者double,警告就会消失,而且能看到正确的浮点数值:
for( auto i : fn<vector>( 1, 2.6, 3 ) ) cout << i << ", " << endl;
另外,你代码里的typeid(common_type_t<int, double>).name()输出的确实是double,这也佐证了common_type_t<int, double, int>的结果是double——因为std::common_type会取所有类型的共同兼容类型,int和double的共同类型就是double。
额外说明
如果想确保容器元素类型是参数包中所有类型的共同类型,你的代码逻辑是正确的:remove_cvref_t用于剥离参数的引用和cv限定符,common_type_t推导所有类型的共同类型,最终容器的元素类型就是这个共同类型。问题只是出在循环时的变量类型声明上。
内容的提问来源于stack exchange,提问作者Edison von Myosotis
相关产品推荐
相关产品推荐

