initializer_list<T>不能转换为 initializer_list<U>,但 T 可转换为 U
initializer_list<T> can't convert to initializer_list<U>, but T convertable to U
考虑以下代码片段...
void boo(std::initializer_list<unsigned> l)
{
}
template <class T>
void foo(std::initializer_list<T> l)
{
//Even though T is convertable, initializer list is not...:-(
boo(move(l));
}
int main()
{
foo({1u,2u,3u}); //Compiles fine as expected
foo({1,2,3}); //Fails to compile at line 9... - could not convert...
return 0;
}
。我很惊讶initializer_list<int>
不能转换为initializer_list<unsigned>
,事件虽然 int 转换为无符号。
我一直想知道可以用什么方式编写 foo 来允许转换。是否可以以某种方式解开具有错误类型的列表并重新创建具有正确类型的新列表?
不。 构造初始值设定项列表需要编译时已知长度,而使用初始值设定项列表时没有编译时已知长度。
初始值设定项列表用于"面向用户"的操作,其中用户是接口的使用者。 像这样在内部使用它们效果不佳。
您可以使用的一种方法是编写一个 array_view<T>
类型,该类型以类似范围视图的方式(使用开始、结束、数据、大小、空、前端、后端方法(包装一系列连续内存(初始值设定项列表、向量、std 数组或 C 数组都是这方面的示例(。 迭代器是指针(。
然后给它隐式转换 ctor 从 vector<T>&
、vector<std::remove_const_t<T>> const&
、initializer_list<std::remove_const_t<T>>
等。
void boo(array_view<const unsigned> l)
{
}
template <class T>
void foo(std::initializer_list<T> l)
{
boo(std::vector<unsigned>{l.begin(), l.end()});
}
go an 根据 l
中的任何内容重新分配unsigned
值的新缓冲区,并将其传递给 boo
。 boo
消耗一个array_view<unsigned const>
,它可以从vector
或unsigned
的initializer_list
转换。
然后我们可以写maybe_convert_list
:
template <class T, class U, class...LowPrecidence>
std::vector<T> maybe_convert_list(std::initializer_list<U> l, LowPrecidence&&...)
{
return {l.begin(), l.end()};
}
template <class T>
std::initializer_list<T> maybe_convert_list(std::initializer_list<T> l)
{
return l;
}
template <class T>
void foo(std::initializer_list<T> l)
{
boo(maybe_convert_list<unsigned>(l));
}
或诸如此类。 它让initializer_list<unsigned>
一个人呆着。 对于其他类型的列表,它会将其转换为 std::vector<unsigned>
.
虽然无法在编译时解压缩初始值设定项列表(以执行必要的转换(,但可以按照所需的方式创建它。请考虑以下代码:
#include <initializer_list>
void boo(std::initializer_list<unsigned> l);
template <class... T>
void foo(T... l)
{
boo({static_cast<unsigned int>(l)...});
}
int main()
{
foo(1,2,3);
return 0;
}
Foo<T>
不能转换为Foo<U>
,即使T
可转换为U
。对于编译器,模板实例化中的不同类型会产生不相关类型的实例。
所以在你的例子中,foo({1,2,3})
推导出T
int
,所以foo
的参数的类型initializer_list<int>
。然后你试着把它传递给boo
,这需要一个initializer_list<unsigned>
,这与initializer_list<int>
无关,因此编译错误。
您可以通过模板专用化来避免这种头痛,即将您的foo
专门化为unsigned
类型:
template<>
void foo<unsigned>(std::initializer_list<unsigned>)
{
// specialization here
}
简而言之,无法进行此转换。一旦你有一个std::initializer_list<int>
对象,就没有办法使用它来合成一个std::initializer_list<unsigned>
。您可以循环访问它,但问题是有关大小的信息无法静态获得,因此无法从一个std::initializer_list
对象生成一个带大括号括起来的初始值设定项列表,用于构造不同的std::initializer_list
对象。
如果boo
需要接收std::initializer_list<unsigned>
,则foo
应该有一个类型为 std::initializer_list<unsigned>
的参数。您可以将{1, 2, 3}
转换为std::initializer_list<unsigned>
。但是一旦你把它推断为std::initializer_list<int>
这种可能性就会消失。
- EASTL矢量<向量<int>>连续的
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- C2664 无法从'initializer list'转换参数
- C++ 错误:"array must be initialized with a brace-enclosed initializer"
- 2D 数组中的"Excess elements in scalar initializer"错误
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 使用 std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"时出错
- 在C++中标记化"Braced Initializer List"样式字符串(使用 Boost?
- std::move in initializer lists
- C 字符串比较“祝您好运”&gt;“再见”
- "Default member initializer needed within definition of enclosing class outside of member functions
- 外部抛出"both extern and initializer"错误
- 从成员构造函数(Brace Initializer vs Initializer列表)抛出异常
- "默认参数":无法从'initializer list'转换为'std::initializer_list'
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- 无法从'initializer-list'转换为用户控制器
- 无法运行简单的 std::async 和 std::future 测试程序。错误:"has initializer but incomplete type."发生了什么?
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- C 操作员&gt;&gt;与突变器过载